    :root {
      /* PVURA Design System 2.0 (DESIGN_SYSTEM_2.md) - the dark, coral-accented
         palette shared conceptually with PVURA Operative's native theme
         tokens. Fixed brand palette, not a per-customer theme - nothing here
         is overridden by org config; every organization sees the same shell.
         Canonical --pvura-* names first (matching the doc + Operative's
         theme.ts 1:1), then the existing --brand/--panel/... names the rest
         of this file already uses are kept as aliases so no selector below
         had to be renamed - only re-pointed at dark values. */
      --pvura-bg: #0b0e11;
      --pvura-surface: #12171b;
      --pvura-surface-raised: #171d22;
      --pvura-surface-soft: #1d242a;
      --pvura-text: #f4f1ea;
      --pvura-text-secondary: #b8bec4;
      --pvura-text-muted: #8e969d;
      --pvura-coral: #ff6b55;
      --pvura-orange: #ff934f;
      --pvura-purple: #3b2e3f;
      --pvura-sand: #e9c5a4;
      --pvura-charcoal: #101214;
      --pvura-success: #39d98a;
      --pvura-warning: #f5b942;
      --pvura-danger: #ff6257;
      --pvura-info: #5fa8ff;
      --pvura-border: rgba(244, 241, 234, 0.10);
      --pvura-border-strong: rgba(244, 241, 234, 0.20);
      --pvura-focus: #ff6b55;
      --pvura-overlay: rgba(11, 14, 17, 0.72);

      --bg-primary: var(--pvura-bg);
      --panel: var(--pvura-surface);
      --panel-raised: var(--pvura-surface-raised);
      --panel-alt: var(--pvura-surface-soft);
      --border: var(--pvura-border);
      --border-strong: var(--pvura-border-strong);
      --ring: rgba(255, 107, 85, 0.18);
      --text-primary: var(--pvura-text);
      --text-secondary: var(--pvura-text-secondary);
      --text-tertiary: var(--pvura-text-muted);

      --brand: var(--pvura-coral);
      /* --brand-hover already served exactly this purpose before this
         sprint (with an almost-identical hand-picked value) - reconciled
         as an alias of the design-lock's canonical --pvura-hover rather
         than kept as a second, near-duplicate hover color (same pattern
         as --radius -> --radius-md above). --pvura-pressed is new: no
         :active state existed on .btn-primary before this sprint. */
      /* Text/border/UI-indicator use of the brand color, split from --brand
         itself (fills, always paired with --on-fill's charcoal text) the
         same way --danger-solid/--danger-text already split status colors
         above. On dark, identical to --brand - --pvura-coral already reads
         fine as text there. On light, overridden to a darkened coral (see
         [data-theme="light"] below) - the bright brand coral fails contrast
         as text/outline on a light ground (2.80:1, below even the 3:1
         non-text minimum). */
      --brand-text: var(--pvura-coral);
      /* Dark surfaces read hover as a brighten-and-lift, not a darken (which
         would read as "receding"), hence lighter/warmer than --brand rather
         than the light theme's darker hover tone. */
      --brand-hover: var(--pvura-hover);
      --brand-soft: rgba(255, 107, 85, 0.14);
      --accent: var(--pvura-orange);
      /* Text placed ON TOP of a solid coral/status fill (primary buttons,
         badges, toast-error) - charcoal reads better than white against
         every one of these mid-bright saturated fills, and matches
         Operative's PrimaryButton (coral bg + charcoal text) exactly. */
      --on-fill: var(--pvura-charcoal);

      /* Status colors on dark: no separate darker "-text" tone is needed
         (unlike the light theme, where saturated fills needed darkened text
         for contrast) - the DS2 status color itself already reads clearly
         against these dark surfaces. -bg/-border stay low-opacity tints of
         the same color rather than filled chips, so status pills read as
         "colored outline + colored text" - the same visual language as
         Operative's StatusPill - just with a faint tint for extra weight in
         dense desktop tables. */
      --danger-solid: var(--pvura-danger);
      --danger-text: var(--pvura-danger);
      --danger-on-fill: var(--on-fill);
      --danger-bg: rgba(255, 98, 87, 0.12);
      --danger-border: rgba(255, 98, 87, 0.4);
      --danger: var(--danger-text);

      --warning-solid: var(--pvura-warning);
      --warning-text: var(--pvura-warning);
      --warning-on-fill: var(--on-fill);
      --warning-bg: rgba(245, 185, 66, 0.12);
      --warning-border: rgba(245, 185, 66, 0.4);
      --warning: var(--warning-text);

      --success-solid: var(--pvura-success);
      --success-text: var(--pvura-success);
      --success-on-fill: var(--on-fill);
      --success-bg: rgba(57, 217, 138, 0.12);
      --success-border: rgba(57, 217, 138, 0.4);
      --success: var(--success-text);

      --info: var(--pvura-info);
      --neutral-bg: var(--pvura-surface-soft);
      --neutral-border: var(--pvura-border-strong);
      --neutral-text: var(--pvura-text-muted);

      /* Multi-Sector Control Experience mission (Section 15/42): one
         narrowly-scoped accent token, touching ONLY the sidebar active-
         indicator below - never --brand/--brand-text itself (PVURA® stays
         one masterbrand, Section 40), never --danger/--warning/--success
         (safety state never depends on sector accent, Section 42). Default
         equals --pvura-coral exactly, so a Fire & Rescue organization (or
         any request with no data-sector attribute) renders byte-identical
         to before this token existed - overridden per [data-sector="..."]
         below for the other four sectors. */
      --sector-accent: var(--pvura-coral);

      --sidebar-width: 248px;
      --sidebar-bg: var(--pvura-charcoal);
      --sidebar-bg-alt: var(--pvura-surface);
      --sidebar-text: var(--pvura-text-secondary);
      --sidebar-text-active: var(--sector-accent);
      --sidebar-hover-bg: rgba(255, 107, 85, 0.10);
      --sidebar-active-bg: rgba(255, 107, 85, 0.16);
      --sidebar-border: rgba(244, 241, 234, 0.08);

      /* --radius-md is the canonical name (Category-Leading UX Design
         Lock, "radius system" / "reconcile carefully, do not create two
         permanent canonical names") - --radius is kept only as an alias
         pointing at it, not a second independent value, so the ~40
         existing var(--radius) call sites across templates/CSS keep
         working unchanged without a repo-wide rename in this sprint. */
      --radius-md: 10px;
      --radius: var(--radius-md);
      --radius-sm: 7px;
      --radius-lg: 16px;
      --radius-full: 999px;

      /* Spacing scale (Category-Leading UX Design Lock, "grid/spacing/
         radius/motion") - documented in DESIGN_SYSTEM_2.md since Fase 1
         but never implemented as real custom properties until now. Existing
         hardcoded spacing values elsewhere in this file are NOT mechanically
         rewritten in this sprint (out of scope, see the design lock's own
         "avoid repository-wide mechanical churn" instruction) - these are
         the canonical target for new/refactored Passport work. */
      --space-1: 4px;
      --space-2: 8px;
      --space-3: 12px;
      --space-4: 16px;
      --space-5: 24px;
      --space-6: 32px;
      --space-7: 48px;
      --space-8: 64px;

      /* Breakpoint values, documented as custom properties for reference/
         JS use - CSS custom properties cannot be read inside an @media
         feature (a hard CSS language limitation, not an implementation
         gap), so every @media rule in this file still spells out the same
         pixel value literally. These three numbers are the single source
         of truth those literals must match. */
      --bp-sm: 480px;
      --bp-md: 768px;
      --bp-lg: 1200px;

      /* New surface/interaction tokens (Category-Leading UX Design Lock,
         "surface hierarchy" / "color tokens"). --pvura-disabled-text locks
         the value already used on PVURA Operative's tokens.ts, closing the
         one token DESIGN_SYSTEM_2.md documented but pvura.css never
         defined. --pvura-hover/--pvura-pressed apply only to the coral
         primary button (see .btn-primary below) - ghost/text buttons keep
         their existing background-tint hover, unchanged. */
      --pvura-surface-critical: #211714;
      --pvura-disabled-text: rgba(244, 241, 234, 0.35);
      --pvura-hover: #ff8269;
      --pvura-pressed: #e8543f;

      /* Typography (Category-Leading UX Design Lock, "typography system")
         - Archivo (display/headings) + Inter (UI/body), the same self-
         hosted variable fonts already shipping on the marketing site
         (marketing-site-src/templates/base.html), extended here rather
         than depending on a third-party font CDN. Fallback stacks are
         DESIGN_SYSTEM_2.md's existing system-sans/mono stacks, used until
         the webfont loads (font-display: swap below) and unchanged if it
         never does. */
      --font-display: 'Archivo', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
      --font-ui: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
      --font-mono: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
      /* Elevation on dark comes primarily from surface steps (bg -> surface
         -> surface-raised -> surface-soft), not heavy shadows - traditional
         black shadows are nearly invisible on a dark ground. Shadows are
         reserved for floating elements (dialogs, toasts) as a thin,
         low-opacity dark shadow plus a visible border for actual legible
         separation (DESIGN_SYSTEM_2.md, "Skygge / elevasjon"). */
      --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
      --shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
      --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.3);

      --motion-fast: 120ms;
      --motion-base: 200ms;
      --motion-slow: 320ms;
      --motion-easing: cubic-bezier(0.22, 1, 0.36, 1);
    }

    /* Personal light-theme opt-in (2026-09) - dark stays PVURA's actual
       target design (CLAUDE.md), this is a per-account preference layered
       on top (users.theme, same shape as users.locale), applied server-
       side as data-theme on <html> so there is no flash of the wrong
       theme on load.

       Every text/status color below was computed against the actual WCAG
       2.1 relative-luminance formula, not eyeballed - all pass AA (>=4.5:1
       for text, >=3:1 for the focus ring as a non-text UI indicator), most
       comfortably clear AAA (>=7:1):
         text-primary   #14181b on #ffffff = 17.85:1 (AAA)
         text-secondary #484e54 on #ffffff =  8.42:1 (AAA)
         text-muted     #5a6167 on #ffffff =  6.28:1 (AA, well past 4.5)
         danger-text    #c4291d on #ffffff =  5.70:1 (AA)
         warning-text   #8a5a00 on #ffffff =  5.93:1 (AA)
         success-text   #1f7a4c on #ffffff =  5.32:1 (AA)
         info           #1d5fbf on #ffffff =  6.10:1 (AA)
         focus ring     #c93a22 on #ffffff =  5.11:1 (AA, exceeds the 3:1
                                                        non-text minimum)
       The base saturated brand/status hues (--pvura-coral/orange/success/
       warning/danger/info) are left untouched - they stay fills/icons
       (paired with --on-fill's charcoal text, itself unaffected since
       --pvura-charcoal doesn't change here), never text color directly;
       only the *-text semantic tokens below get a darkened variant, the
       same distinction this file's own dark-theme comments already
       anticipated ("unlike the light theme, where saturated fills needed
       darkened text for contrast" - see --danger-text above). --pvura-
       coral itself fails badly as text/outline on white (2.80:1) - that's
       exactly why it's never reassigned to a *-text token here. */
    [data-theme="light"] {
      --pvura-bg: #ffffff;
      --pvura-surface: #f7f5f2;
      --pvura-surface-raised: #ffffff;
      --pvura-surface-soft: #efede8;
      --pvura-text: #14181b;
      --pvura-text-secondary: #484e54;
      --pvura-text-muted: #5a6167;
      --pvura-border: rgba(20, 24, 27, 0.10);
      --pvura-border-strong: rgba(20, 24, 27, 0.20);
      --pvura-focus: #c93a22;
      --pvura-overlay: rgba(20, 24, 27, 0.5);

      /* Light surfaces read hover as a press-down/darken, not a lift -
         the opposite of dark mode's brighten (see --brand-hover's own
         comment above). */
      --brand-hover: var(--pvura-hover);
      --brand-text: #c93a22;
      --ring: rgba(201, 58, 34, 0.35);

      --danger-text: #c4291d;
      --danger: var(--danger-text);
      --warning-text: #8a5a00;
      --warning: var(--warning-text);
      --success-text: #1f7a4c;
      --success: var(--success-text);
      --info: #1d5fbf;
      --neutral-text: var(--pvura-text-muted);

      /* Light-theme equivalents for the new tokens added in this sprint
         (Category-Leading UX Design Lock §2.3: "no new light-theme design
         debt" - every new token gets an explicit light value here, not left
         undefined). --pvura-surface-critical becomes a light, warm-tinted
         ground (not the dark theme's near-black tint) so a Level-4 card
         still reads as "distinct from the page", not as a stray dark box on
         a white page. Light already reads hover as press-down/darken (see
         --brand-hover above), so --pvura-hover/--pvura-pressed follow the
         same direction here, not dark mode's brighten. */
      --pvura-surface-critical: #fdf1ef;
      --pvura-disabled-text: rgba(20, 24, 27, 0.35);
      --pvura-hover: #e85a44;
      --pvura-pressed: #c94a35;

      /* The left nav rail switches to light too (2026-09-05: a fully
         light theme, not a dark-chrome/light-canvas split - an earlier
         version of this pass kept it dark, but that read as broken/
         half-applied rather than deliberate). A shade off pure white
         (matching --pvura-surface) for gentle separation from the main
         content, not identical to it. --sidebar-text-active now derives
         from --brand-text above instead of a literal value, so it stays
         correct in both themes automatically. */
      --sidebar-bg: #f7f5f2;
      --sidebar-bg-alt: #efede8;
      --sidebar-text: #484e54;
      /* --sector-accent itself is NOT redefined here - it stays the dark-
         mode hex from :root/[data-sector] above (same cross-theme literal
         the pre-existing --sidebar-hover-bg/--sidebar-active-bg rgba
         tints already used - unchanged by this mission). Only the ACTIVE
         TEXT needs a darkened, light-background-safe variant, mirroring
         --brand-text's own light-mode darkening immediately above for the
         identical contrast reason; --sector-accent-text-light provides
         that per sector, defaulting to --brand-text's own light value. */
      --sector-accent-text-light: var(--brand-text);
      --sidebar-text-active: var(--sector-accent-text-light);
      --sidebar-hover-bg: rgba(255, 107, 85, 0.10);
      --sidebar-active-bg: rgba(255, 107, 85, 0.16);
      --sidebar-border: rgba(20, 24, 27, 0.08);
    }

    /* SUPERSEDED 2026-10-05 (Sector Experience V2): the Multi-Sector
       mission's invented --sector-accent values (maritime #3fb8d4, offshore
       #c97d3a, energy #7c6cff, industry #5a93a0, fire = coral) are replaced
       by the product-owner-approved V2 sector palettes, defined once in
       static/css/pvura-control.css under [data-sector=...] and documented
       in sector_experience.py / DESIGN_SYSTEM_2.md. --sector-accent is kept
       as an alias of the V2 --sector-bright token so older selectors keep
       resolving. */

    /* Self-hosted, not a third-party font CDN dependency - same two files
       already shipping on the marketing site (marketing-site-src/templates/
       base.html), copied into static/fonts/ for this app rather than linked
       externally. Variable fonts (weight 100-900 in one file), font-display:
       swap so text is never invisible while they load. */
    @font-face {
      font-family: 'Archivo';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url('../fonts/Archivo-var.woff2') format('woff2');
    }
    @font-face {
      font-family: 'Inter';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url('../fonts/Inter-var.woff2') format('woff2');
    }

    * { box-sizing: border-box; }
    html { scroll-behavior: smooth; }

    /* Brand-accent scrollbar (coral -> orange, matching the app's own accent
       pair) instead of the browser default - applies everywhere, not just
       one surface. Firefox has no gradient support for scrollbar-color, so
       it falls back to a flat coral thumb. */
    html {
      scrollbar-width: thin;
      scrollbar-color: var(--pvura-coral) transparent;
    }

    ::-webkit-scrollbar { width: 10px; height: 10px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb {
      background: linear-gradient(180deg, var(--pvura-orange), var(--pvura-coral));
      border-radius: 999px;
      border: 2px solid var(--bg-primary);
      background-clip: padding-box;
    }
    ::-webkit-scrollbar-thumb:hover {
      background: linear-gradient(180deg, var(--pvura-coral), var(--pvura-orange));
      background-clip: padding-box;
    }
    body {
      margin: 0;
      font-family: var(--font-ui);
      background: var(--bg-primary);
      color: var(--text-primary);
      min-height: 100vh;
      -webkit-font-smoothing: antialiased;
    }

    a { color: inherit; text-decoration: none; }

    /* Base heading rhythm - most headings inherit this untouched; .hero h1
       and .card-header h2/h3 layer stronger, context-specific treatment on
       top. Without this, any <h2>/<h3> outside those two patterns fell back
       to browser defaults, which is a big part of why the interface read as
       flat at desktop size - every heading looked like plain text. */
    h1, h2, h3, h4, h5, h6 {
      margin: 0 0 0.5em;
      font-family: var(--font-display);
      font-weight: 700;
      letter-spacing: -0.01em;
      color: var(--text-primary);
      line-height: 1.25;
    }

    h1 { font-size: 1.9rem; letter-spacing: -0.02em; }
    h2 { font-size: 1.35rem; }
    h3 { font-size: 1.1rem; }
    h4, h5, h6 { font-size: 1rem; font-weight: 600; }

    /* Visible, on-brand keyboard focus everywhere - DS2 requires a real
       ring, never just a color change (see --pvura-focus). Native
       :focus-visible support means mouse/touch interaction never shows it. */
    a:focus-visible,
    button:focus-visible,
    .btn:focus-visible,
    .sidebar-link:focus-visible,
    .nav-links a:focus-visible,
    .link:focus-visible,
    [tabindex]:focus-visible {
      outline: 2px solid var(--pvura-focus);
      outline-offset: 2px;
      border-radius: var(--radius-sm);
    }

    /* Skip-link (UX Phase 3C, P3) - the very first focusable element in
       body, positioned off-screen via `top` (not display:none/visibility:
       hidden, which would also remove it from the tab order) so it never
       shifts surrounding layout, then slides into view on :focus. Works
       with zero JavaScript - pure CSS + the browser's own fragment-focus
       behavior on #main-content (tabindex="-1" there makes a non-
       interactive landmark programmatically focusable without joining the
       normal tab sequence). */
    .skip-link {
      position: absolute;
      top: -60px;
      left: 12px;
      z-index: 1000;
      background: var(--brand);
      color: var(--on-fill);
      font-weight: 700;
      padding: 0.85rem 1.4rem;
      border-radius: var(--radius-sm);
      text-decoration: none;
      transition: top var(--motion-fast) ease;
    }

    .skip-link:focus {
      top: 12px;
      outline: 2px solid var(--pvura-focus);
      outline-offset: 2px;
    }

    @media (prefers-reduced-motion: reduce) {
      .skip-link { transition: none; }
    }

    /* Breadcrumbs (UX Phase 3C, P3) - quiet, tertiary orientation for
       genuinely nested/detail pages only (not every screen - most routes
       never pass `breadcrumbs` at all, so this renders nothing for them).
       Deliberately not a card/bar with a background - a single small,
       muted text line reads as "you are here", not a second nav. */
    .breadcrumb-bar { margin-bottom: 16px; }
    .breadcrumb-bar ol {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 6px;
      margin: 0;
      padding: 0;
      list-style: none;
      font-size: 0.85rem;
    }
    .breadcrumb-bar li { display: flex; align-items: center; gap: 6px; min-width: 0; }
    .breadcrumb-bar a {
      color: var(--text-secondary);
      text-decoration: none;
      max-width: 220px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .breadcrumb-bar a:hover { color: var(--text-primary); text-decoration: underline; }
    .breadcrumb-bar span[aria-current] {
      color: var(--text-primary);
      font-weight: 600;
      max-width: 320px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .breadcrumb-bar .breadcrumb-sep { color: var(--text-tertiary); }

    @media (max-width: 480px) {
      .breadcrumb-bar a { max-width: 120px; }
      .breadcrumb-bar span[aria-current] { max-width: 160px; }
    }

    .container {
      width: min(1320px, calc(100% - 32px));
      margin: 0 auto;
    }

    /* ---------- App shell: sidebar (desktop) + main area ---------- */

    .app-shell {
      display: flex;
      min-height: 100vh;
    }

    .sidebar {
      display: none;
      flex-direction: column;
      width: var(--sidebar-width);
      flex-shrink: 0;
      background: var(--sidebar-bg);
      color: var(--sidebar-text);
      position: sticky;
      top: 0;
      height: 100vh;
      overflow-y: auto;
    }

    .sidebar-brand {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 22px 20px;
      color: var(--pvura-text);
      font-weight: 700;
      font-size: 1.05rem;
      letter-spacing: -0.01em;
      border-bottom: 1px solid var(--sidebar-border);
    }

    .sidebar-brand span {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .sidebar-nav {
      flex: 1;
      padding: 16px 12px;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    .sidebar-nav-label {
      font-size: 0.72rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: var(--sidebar-text);
      opacity: 0.6;
      padding: 18px 12px 8px;
    }

    .sidebar-nav-label:first-child { padding-top: 4px; }

    /* Sized up (2026-09) - removing the account-action links that used to
       sit in a separate sidebar-footer (now consolidated into the
       user-chip dropdown, top right) freed real vertical room here. */
    .sidebar-link {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 0.8rem 0.85rem;
      border-radius: var(--radius-sm);
      font-size: 1rem;
      font-weight: 600;
      color: var(--sidebar-text);
      /* A left accent bar (inset box-shadow, not a real border) marks the
         current page - precise and legible, not a glow. box-shadow rather
         than border-left so it never shifts layout/padding when it appears. */
      box-shadow: inset 2px 0 0 transparent;
      transition: background-color var(--motion-fast) ease, color var(--motion-fast) ease, box-shadow var(--motion-fast) ease;
    }

    .sidebar-link svg {
      flex-shrink: 0;
      width: 23px;
      height: 23px;
      opacity: 0.75;
      transition: opacity var(--motion-fast) ease;
    }

    .sidebar-link:hover {
      background: var(--sidebar-hover-bg);
      color: var(--sidebar-text-active);
    }

    .sidebar-link:hover svg { opacity: 1; }

    .sidebar-link.active {
      background: var(--sidebar-active-bg);
      color: var(--sidebar-text-active);
      box-shadow: inset 2px 0 0 var(--brand-text);
    }

    .sidebar-link.active svg { opacity: 1; }

    @media (prefers-reduced-motion: reduce) {
      .sidebar-link, .sidebar-link svg { transition: none; }
    }

    /* Collapsed-by-default sub-group inside a sidebar category (e.g.
       "Eksport" tucked under Verneutstyr) - a native <details> disclosure,
       no JS, auto-opens itself via the `open` attribute when one of its own
       links is the active page (see the endpoint check in the template). */
    .sidebar-group summary {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 0.8rem 0.85rem;
      border-radius: var(--radius-sm);
      font-size: 1rem;
      font-weight: 600;
      color: var(--sidebar-text);
      cursor: pointer;
      list-style: none;
      transition: background-color 0.15s ease, color 0.15s ease;
    }

    .sidebar-group summary::-webkit-details-marker { display: none; }

    .sidebar-group summary:hover {
      background: var(--sidebar-hover-bg);
      color: var(--sidebar-text-active);
    }

    .sidebar-group[open] > summary { color: var(--sidebar-text-active); }

    .sidebar-group summary .chevron {
      flex-shrink: 0;
      opacity: 0.6;
      transition: transform 0.15s ease;
    }

    .sidebar-group[open] > summary .chevron { transform: rotate(90deg); }

    .sidebar-group .sidebar-link { padding-left: 2.35rem; }

    @media (prefers-reduced-motion: reduce) {
      .sidebar-group summary, .sidebar-group summary .chevron { transition: none; }
    }

    .sidebar-link .nav-badge { margin-left: auto; }

    .main-area {
      flex: 1;
      min-width: 0;
      display: flex;
      flex-direction: column;
    }

    .topbar {
      background: var(--panel);
      border-bottom: 1px solid var(--border);
      position: sticky;
      top: 0;
      z-index: 20;
    }

    .topbar-inner {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      align-items: center;
      min-height: 72px;
      gap: 12px 24px;
      padding: 12px 20px;
    }

    .brand {
      display: inline-flex;
      align-items: center;
      gap: 12px;
      font-weight: 700;
      letter-spacing: -0.01em;
      font-size: 1.05rem;
      color: var(--text-primary);
    }

    .brand-mark {
      width: 40px;
      height: 40px;
      display: grid;
      place-items: center;
      border-radius: 9px;
      background: var(--brand);
      font-size: 1.1rem;
      overflow: hidden;
      flex-shrink: 0;
    }

    .brand-mark img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    /* pvura__ wordmark - lowercase, double underscore rendered as two
       separate ticks (never a literal "__" glyph run, which some fonts
       collapse into one continuous underscore). Mirrors marketing-site's
       .brand-word / Operative's Brand.tsx Wordmark 1:1. */
    .brand-word {
      display: inline-flex;
      align-items: baseline;
      font-weight: 800;
      letter-spacing: -0.01em;
      color: var(--pvura-text);
    }

    .brand-word .us1 {
      color: var(--brand-text);
    }

    .brand-word .us2 {
      /* --pvura-orange itself fails as text on light (2.20:1) the same way
         --pvura-coral does - darkened inline rather than via a new
         --accent-text token, since this is the only place --pvura-orange
         is ever used as text/an outline color in this file. #b85a00 on
         white = 4.67:1 (AA). Dark mode is untouched (still the bright
         accent, which already read fine there). */
      color: var(--pvura-orange);
      margin-left: 0.14em;
    }

    [data-theme="light"] .brand-word .us2 { color: #b85a00; }

    /* Horizontal line-motif signature - used sparingly (login screen only),
       never as generic decoration under every heading. */
    .topbar-actions {
      display: flex;
      align-items: center;
      gap: 10px;
      flex-wrap: wrap;
      margin-left: auto;
    }

    .nav-links {
      display: flex;
      align-items: center;
      gap: 2px;
      overflow-x: auto;
      padding: 10px 0;
      border-top: 1px solid var(--border);
      -webkit-overflow-scrolling: touch;
    }

    .nav-links a {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      white-space: nowrap;
      padding: 0.45rem 0.85rem;
      border-radius: var(--radius-sm);
      font-size: 0.86rem;
      font-weight: 600;
      color: var(--text-secondary);
      transition: background-color 0.12s ease, color 0.12s ease;
    }

    .nav-links a:hover {
      background: var(--panel-alt);
      color: var(--text-primary);
    }

    .nav-links a.active {
      /* Multi-Sector Control Experience mission: reuses the sidebar's own
         already-sector-/theme-aware tokens (--sidebar-active-bg/
         --sidebar-text-active) instead of the universal --brand-soft/
         --brand-text, so the mobile top-nav's active tab matches the
         desktop sidebar's accent for the same organization - previously
         this was the one place the two navs visibly disagreed. Fire &
         Rescue's resolved values are unchanged from the pre-mission
         --brand-soft/--brand-text ones (same coral, same opacity). */
      background: var(--sidebar-active-bg);
      color: var(--sidebar-text-active);
      /* Fire & Rescue's resolved values are visually the same coral as
         before (0.16 vs the prior --brand-soft's 0.14 alpha - a
         difference too small to read as a regression) and the same
         --pvura-coral text. */
    }

    .nav-badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 18px;
      height: 18px;
      padding: 0 5px;
      border-radius: 999px;
      background: var(--danger-solid);
      color: white;
      font-size: 0.68rem;
      font-weight: 700;
    }

    .desktop-header { display: none; }

    /* Desktop: swap the mobile topbar/nav-links for the sidebar + a slim header */
    @media (min-width: 960px) {
      .sidebar { display: flex; }
      .mobile-chrome { display: none; }

      .desktop-header {
        display: flex;
        align-items: center;
        gap: 20px;
        min-height: 72px;
        padding: 0 32px;
        background: var(--panel);
        border-bottom: 1px solid var(--border);
        position: sticky;
        top: 0;
        z-index: 15;
      }

      .desktop-header .search-input { max-width: 360px; }

      /* Groups the bell with the user chip (not with search/scan) - the
         group as a whole is pushed to the far right, but the bell sits
         tight against the name/avatar instead of at the default 20px
         header gap (2026-09 placement fix). */
      .header-user-group {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-left: auto;
      }

      .user-chip {
        position: relative;
      }

      .user-chip summary {
        display: flex;
        align-items: center;
        gap: 10px;
        list-style: none;
        cursor: pointer;
        padding: 4px;
        border-radius: 12px;
      }

      .user-chip summary::-webkit-details-marker { display: none; }
      .user-chip summary:hover { background: var(--panel-alt); }
      .user-chip[open] summary { background: var(--panel-alt); }

      .user-chip-avatar {
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: var(--brand-soft);
        color: var(--brand-text);
        display: grid;
        place-items: center;
        font-weight: 700;
        font-size: 0.85rem;
        flex-shrink: 0;
      }

      .user-chip-text { line-height: 1.25; }
      .user-chip-name { font-weight: 700; font-size: 0.88rem; color: var(--text-primary); }
      .user-chip-role { font-size: 0.76rem; color: var(--text-tertiary); }

      .user-chip-menu {
        position: absolute;
        top: calc(100% + 6px);
        right: 0;
        min-width: 180px;
        background: var(--panel-raised);
        border: 1px solid var(--border-strong);
        border-radius: 12px;
        box-shadow: var(--shadow-md);
        padding: 6px;
        z-index: 20;
        display: flex;
        flex-direction: column;
        gap: 2px;
      }

      .user-chip-menu a {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 10px;
        border-radius: 8px;
        color: var(--text-primary);
        text-decoration: none;
        font-size: 0.88rem;
        font-weight: 600;
      }

      .user-chip-menu a:hover { background: var(--panel-alt); }

      .user-chip-menu a .nav-badge { margin-left: auto; }

      /* Tilbakemelding is a JS-triggered dialog (feedback-dialog), not a
         link - same look as the <a> rows above, reset from a bare
         <button>. */
      .user-chip-menu button {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 10px;
        border: none;
        background: none;
        border-radius: 8px;
        color: var(--text-primary);
        font: inherit;
        font-size: 0.88rem;
        font-weight: 600;
        text-align: left;
        width: 100%;
        cursor: pointer;
      }

      .user-chip-menu button:hover { background: var(--panel-alt); }

      .user-chip-menu-divider {
        height: 1px;
        background: var(--border);
        margin: 4px 2px;
      }

      .theme-toggle-form { padding: 4px 10px 6px; }

      .theme-toggle {
        display: flex;
        align-items: center;
        gap: 10px;
        cursor: pointer;
      }

      /* Visually hidden but still a real, focusable checkbox - the track
         and thumb spans right after it are what's actually shown, driven
         by :checked, so keyboard/screen-reader users get the native
         control's semantics for free rather than a div pretending to be
         one. */
      .theme-toggle input {
        position: absolute;
        opacity: 0;
        width: 1px;
        height: 1px;
      }

      .theme-toggle-track {
        width: 38px;
        height: 22px;
        border-radius: var(--radius-full);
        background: var(--border-strong);
        position: relative;
        flex-shrink: 0;
        transition: background-color var(--motion-base) var(--motion-easing);
      }

      .theme-toggle-thumb {
        position: absolute;
        top: 2px;
        left: 2px;
        width: 18px;
        height: 18px;
        border-radius: 50%;
        background: var(--pvura-text);
        transition: transform var(--motion-base) var(--motion-easing), background-color var(--motion-base) var(--motion-easing);
      }

      .theme-toggle input:checked ~ .theme-toggle-track { background: var(--brand); }

      .theme-toggle input:checked ~ .theme-toggle-track .theme-toggle-thumb {
        transform: translateX(16px);
        background: var(--on-fill);
      }

      .theme-toggle input:focus-visible ~ .theme-toggle-track {
        outline: 2px solid var(--pvura-focus);
        outline-offset: 2px;
      }

      .theme-toggle-label { font-size: 0.88rem; font-weight: 600; color: var(--text-secondary); }

      @media (prefers-reduced-motion: reduce) {
        .theme-toggle-track, .theme-toggle-thumb { transition: none; }
      }
    }

    .feedback-dialog {
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-lg);
      background: var(--panel-raised);
      color: var(--text-primary);
      padding: 1.6rem;
      width: min(480px, calc(100% - 40px));
      box-shadow: var(--shadow-md);
    }

    .feedback-dialog::backdrop {
      background: var(--pvura-overlay);
    }

    .scan-dialog {
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-lg);
      background: var(--panel-raised);
      color: var(--text-primary);
      padding: 1.6rem;
      width: min(440px, calc(100% - 40px));
      box-shadow: var(--shadow-md);
    }

    .scan-dialog::backdrop {
      background: var(--pvura-overlay);
    }

    .scan-video {
      display: none;
      width: 100%;
      aspect-ratio: 4 / 3;
      object-fit: cover;
      border-radius: var(--radius-sm);
      background: #000;
      margin-bottom: 10px;
    }

    .scan-status {
      color: var(--text-secondary);
      font-size: 0.85rem;
      margin: 0 0 14px;
    }

    .scan-photo-fallback {
      margin-top: 10px;
      text-align: center;
    }

    .scan-photo-fallback .btn {
      font-size: 0.82rem;
      padding: 0.5rem 1rem;
    }

    .btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      min-height: 44px;
      padding: 0.6rem 1.15rem;
      border-radius: 12px;
      border: 1px solid transparent;
      font-weight: 700;
      font-size: 0.9rem;
      cursor: pointer;
      transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
    }

    /* Sector Experience V2 (2026-10-05): the primary action is NEUTRAL in
       every sector - ivory on the dark shell, anthracite in the light
       theme. Supersedes the universal coral CTA: with five sector accents
       (one of them red, one orange) a coloured primary button would read as
       either a sector signal or a safety signal. Coral remains the PVURA
       masterbrand colour (logo, marketing), not an action colour. */
    .btn-primary {
      background: var(--action-bg);
      color: var(--action-fg);
      border-color: var(--action-bg);
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    }

    .btn-primary:hover {
      background: var(--action-bg-hover);
      border-color: var(--action-bg-hover);
      transform: translateY(-1px);
    }

    .btn-primary:active {
      background: var(--action-bg-pressed);
      transform: translateY(0);
    }

    .btn-secondary {
      background: var(--panel-raised);
      border-color: var(--border-strong);
      color: var(--text-primary);
    }

    .btn-secondary:hover {
      background: var(--panel-alt);
      border-color: var(--pvura-text-muted);
      transform: translateY(-1px);
    }

    .btn-ghost {
      background: transparent;
      border-color: transparent;
      color: var(--text-secondary);
    }

    .btn-ghost:hover {
      color: var(--text-primary);
      background: var(--panel-alt);
    }

    .btn-danger {
      background: var(--danger-bg);
      border-color: var(--danger-border);
      color: var(--danger);
    }

    .btn-danger:hover {
      background: rgba(255, 98, 87, 0.2);
    }

    .btn:disabled,
    .btn[disabled] {
      opacity: 0.5;
      cursor: not-allowed;
      transform: none !important;
      box-shadow: none !important;
    }

    .pagination-bar {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 16px;
      margin-top: 20px;
      padding-top: 16px;
      border-top: 1px solid var(--border-subtle, var(--border-strong));
    }

    .pagination-btn {
      min-height: 36px;
      padding: 0.4rem 0.9rem;
      font-size: 0.84rem;
      font-weight: 600;
    }

    .pagination-btn-disabled {
      opacity: 0.4;
      cursor: not-allowed;
    }

    .pagination-range {
      color: var(--text-tertiary);
      font-size: 0.82rem;
      font-variant-numeric: tabular-nums;
    }

    .page-shell { padding: 28px 0 52px; }

    .hero {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 24px;
      margin-bottom: 32px;
      padding-bottom: 24px;
      border-bottom: 1px solid var(--border);
    }

    .hero-content { flex: 1; }

    .hero h1 {
      margin: 0;
      font-size: clamp(1.7rem, 3.4vw, 2.6rem);
      font-weight: 800;
      letter-spacing: -0.03em;
      color: var(--text-primary);
    }

    .hero-sub {
      margin: 8px 0 0;
      color: var(--text-secondary);
      font-size: 1.05rem;
      max-width: 56ch;
    }

    /* Small uppercase eyebrow naming which PVURA product area a page
       belongs to - used sparingly, only where a page could otherwise read
       as ambiguous about which area it's part of. */
    .area-label {
      margin: 0 0 4px;
      font-size: 0.72rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: var(--text-tertiary);
    }

    .stats {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 14px;
      margin-bottom: 24px;
    }

    .stat-card {
      /* Elevation via a surface step (surface-raised, one step up from the
         page bg), not a shadow - traditional shadows read as nearly
         invisible on a dark ground (DESIGN_SYSTEM_2.md, "Skygge/elevasjon"). */
      background: var(--panel-raised);
      border: 1px solid var(--border);
      border-left: 3px solid var(--border-strong);
      border-radius: 14px;
      padding: 1.25rem 1.4rem;
      min-height: 116px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      transition: border-color var(--motion-fast) ease, background-color var(--motion-fast) ease, transform var(--motion-fast) ease;
    }

    .stat-card:is(a):hover {
      background: var(--panel-alt);
      border-left-color: var(--brand-text);
      transform: translateY(-1px);
    }

    .stat-card.overdue { border-left-color: var(--danger); }
    .stat-card.due-soon { border-left-color: var(--warning); }
    .stat-card.ok { border-left-color: var(--success); }

    .stat-label {
      color: var(--text-secondary);
      font-size: 0.8rem;
      font-weight: 600;
      margin-bottom: 8px;
    }

    .stat-value {
      font-size: clamp(1.6rem, 4vw, 2.2rem);
      font-weight: 700;
      letter-spacing: -0.02em;
      line-height: 1;
      color: var(--text-primary);
    }

    .card {
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 16px;
      padding: 1.5rem;
      margin-bottom: 20px;
    }

    /* Interactive card variant - a hoverable/clickable .card (list rows
       rendered as cards, etc.) gets a visible lift on hover/focus so it
       reads as actionable, matching the "Interactive" card contract from
       DESIGN_SYSTEM_2.md's component inventory. */
    a.card:hover, .card.is-interactive:hover {
      background: var(--panel-alt);
      border-color: var(--border-strong);
    }

    /* Calm accent cards: a colored left edge + a colored icon/heading on an
       otherwise neutral card. No gradients, no full-bleed color blocks - color
       marks "this needs attention", it doesn't decorate. */
    .card.accent-warning,
    .card.accent-danger {
      border-left: 3px solid transparent;
    }

    .card.accent-warning { border-left-color: var(--warning-solid); }
    .card.accent-danger { border-left-color: var(--danger-solid); }

    .accent-heading {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .accent-heading svg { flex-shrink: 0; }
    .accent-heading.warning { color: var(--warning-text); }
    .accent-heading.danger { color: var(--danger-text); }
    .accent-heading.warning h2, .accent-heading.danger h2 { color: inherit; }

    /* ==========================================================================
       Equipment Passport foundation (Category-Leading UX Design Lock, Sprint 1)
       - surface hierarchy (Level 0-4), the State/Reason/Action stack, the
       Passport hero/grid layout, DataRow, LifecycleRail and DangerZone.
       These are the primitives future PVURA surfaces inherit - built here
       because the Passport is the first screen that needs them, not
       reskinning every existing .card in the app. ========================= */

    /* Level 3 - raised/action surface: used when the user is expected to
       act (the Passport hero, primary forms). One elevation token, applied
       consistently - never a second, competing shadow value. */
    .surface-raised {
      background: var(--panel-raised);
      border: 1px solid var(--border-strong);
      box-shadow: var(--shadow);
    }

    /* Level 4 - critical attention surface: a non-Ready State/Reason/Action
       stack, a blocking-deviation row, a danger-zone card. Distinguished by
       a warm-tinted background AND a 3px semantic-colored left edge - never
       color alone, matching the same "color + word" discipline status pills
       already follow. .surface-critical.tone-warning swaps the edge/tint to
       warning for the less-severe cases (control due, non-blocking avvik)
       that don't warrant the full danger treatment. */
    .surface-critical {
      background: var(--pvura-surface-critical);
      border: 1px solid var(--danger-border);
      border-left: 3px solid var(--danger-solid);
    }

    .surface-critical.tone-warning {
      background: var(--warning-bg);
      border-color: var(--warning-border);
      border-left-color: var(--warning-solid);
    }

    .surface-critical.tone-neutral {
      background: var(--panel-raised);
      border-color: var(--border-strong);
      border-left-color: var(--pvura-text-muted);
    }

    /* ---------- State / Reason / Action stack ----------
       The single most important primitive in the target design: status,
       then (if applicable) why, then what happens next - always in this
       order, always structurally together, never split across separate
       cards. A Ready item renders only .sra-status; the reason/action rows
       are simply absent (not empty), which is itself the "nothing to see
       here" signal - see .sra-status-only below. */
    .sra {
      display: flex;
      flex-direction: column;
      gap: var(--space-2);
      padding: var(--space-4) var(--space-5);
      border-radius: var(--radius-lg);
      min-width: 260px;
    }

    .sra .status-pill {
      padding: 0.5rem 0.95rem;
      font-size: 0.85rem;
      align-self: flex-start;
    }

    .sra-reason,
    .sra-action {
      font-size: 0.92rem;
      color: var(--text-secondary);
      line-height: 1.5;
    }

    .sra-reason strong,
    .sra-action strong {
      color: var(--text-primary);
      font-weight: 700;
    }

    .sra-action { color: var(--text-primary); font-weight: 600; }

    /* Quiet/Ready variant - no critical surface, no reason/action rows,
       deliberately less visual content than every other state (Category-
       Leading UX Design Lock §31, "Ready should feel quiet"). */
    .sra.sra-quiet { padding: var(--space-3) var(--space-4); }

    /* ZERO-TOUCH 2: a next-action the current user can't personally
       perform (e.g. release, admin-only) is still named - never hidden -
       but visually distinguished from a clickable one via this quieter
       inline note rather than a link. */
    .sra-admin-note { font-weight: 400; color: var(--text-secondary); font-size: 0.85rem; }

    /* Secondary reasons - other active readiness reasons besides the
       primary one (only ever appears when the engine genuinely reports
       more than one, e.g. a blocking deviation AND a pending repair at
       once). Deliberately no bullet-heavy styling or its own action
       link - one primary call-to-action per Passport, these are
       informational context, not a second competing CTA. */
    .sra-secondary-reasons {
      margin: 0;
      padding: 0;
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .sra-secondary-reasons li {
      font-size: 0.85rem;
      color: var(--text-secondary);
    }

    /* ---------- Passport layout ---------- */

    .passport-hero {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-start;
      justify-content: space-between;
      gap: var(--space-6);
      padding: var(--space-6);
      border-radius: var(--radius-lg);
      margin-bottom: var(--space-6);
    }

    .passport-identity { min-width: 240px; flex: 1; }

    .passport-eyebrow {
      margin: 0 0 4px;
      font-size: 0.78rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      color: var(--text-tertiary);
    }

    .passport-title {
      margin: 0;
      font-family: var(--font-display);
      font-size: clamp(1.7rem, 3.2vw, 2.1rem);
      font-weight: 800;
      letter-spacing: -0.02em;
      color: var(--text-primary);
    }

    .passport-subline {
      margin: 4px 0 0;
      color: var(--text-secondary);
      font-size: 0.95rem;
    }

    .passport-hero-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-top: var(--space-3);
    }

    /* Max width narrower than the general .container (1140px vs 1320px,
       Category-Leading UX Design Lock §D) - a Passport is read, not
       scanned like a dense register, and a narrower measure keeps line
       lengths and the two-column split legible. */
    .passport-container {
      width: min(1140px, calc(100% - 32px));
      margin: 0 auto;
    }

    .passport-grid {
      display: grid;
      grid-template-columns: minmax(0, 62%) minmax(0, 1fr);
      gap: var(--space-6);
      align-items: start;
    }

    .passport-main, .passport-aside { min-width: 0; }

    /* No sticky aside - considered and rejected (design lock §22: "the
       design lock rejected sticky-by-default"). A sticky rail fights the
       main column's own scroll length at this content size for no real
       usability gain, and adds real implementation risk for nothing. */

    @media (max-width: 1200px) {
      .passport-grid { grid-template-columns: 1fr; }
    }

    /* ---------- DataRow: label/value metadata, never a nested card ----------
       Directly answers "stop nesting cards inside cards" - a DataRow is a
       plain row with a hairline divider, living inside one already-
       established surface, never its own bordered box. */
    .data-row-list { display: flex; flex-direction: column; }

    .data-row {
      display: flex;
      justify-content: space-between;
      align-items: baseline;
      gap: var(--space-4);
      padding: var(--space-3) 0;
      border-bottom: 1px solid var(--border);
    }

    .data-row:last-child { border-bottom: none; }

    .data-row-label {
      color: var(--text-tertiary);
      font-size: 0.78rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.04em;
      flex-shrink: 0;
    }

    .data-row-value {
      color: var(--text-primary);
      font-size: 0.92rem;
      font-weight: 600;
      text-align: right;
      font-variant-numeric: tabular-nums;
    }

    /* ---------- LifecycleRail: the second major PVURA signature ----------
       High-significance events (exposure, blocking deviation, quarantine,
       repair, release, retirement) render at full weight; routine events
       (cleaning, normal inspection, assignment) collapse to a single
       compact line. Both share the same severity-accented left border
       language the rest of the surface hierarchy already uses. */
    .lifecycle-rail {
      display: flex;
      flex-direction: column;
      gap: var(--space-2);
    }

    .lifecycle-event {
      display: flex;
      gap: var(--space-3);
      border-left: 3px solid var(--border-strong);
      padding: var(--space-3) var(--space-4);
      border-radius: var(--radius-sm);
    }

    .lifecycle-event-date {
      min-width: 88px;
      font-size: 0.82rem;
      color: var(--text-secondary);
      white-space: nowrap;
      font-variant-numeric: tabular-nums;
    }

    .lifecycle-event-title { font-weight: 600; color: var(--text-primary); }

    .lifecycle-event-summary {
      font-size: 0.85rem;
      color: var(--text-secondary);
      margin-top: 2px;
    }

    .lifecycle-event-actor {
      font-size: 0.78rem;
      color: var(--text-tertiary);
      margin-top: 2px;
    }

    /* High-significance: full padding/weight, colored left edge matching
       the event's own semantic tone (danger/warning/success - never a
       sector color, see the design lock's sector-accent isolation rule). */
    .lifecycle-event.is-major {
      background: var(--panel-alt);
      padding: var(--space-4);
    }

    .lifecycle-event.tone-danger { border-left-color: var(--danger-solid); }
    .lifecycle-event.tone-warning { border-left-color: var(--warning-solid); }
    .lifecycle-event.tone-success { border-left-color: var(--success-solid); }
    .lifecycle-event.tone-info { border-left-color: var(--info); }

    /* Routine: compact single line, no summary/actor rows, minimal padding -
       deliberately less visually prominent than a major event, never the
       reverse. */
    .lifecycle-event.is-routine {
      padding: var(--space-2) var(--space-4);
      align-items: baseline;
    }

    .lifecycle-event.is-routine .lifecycle-event-title {
      font-weight: 500;
      font-size: 0.9rem;
    }

    /* ---------- DangerZone: one shared irreversible-action pattern ----------
       Ports the existing person-delete "Farlig sone" example (the best
       pattern already in the product, per the UX audit) into a reusable
       class, rather than leaving it a one-off. */
    .danger-zone {
      border: 1px solid var(--danger-border);
      border-left: 3px solid var(--danger-solid);
      border-radius: var(--radius-lg);
      background: var(--pvura-surface-critical);
      padding: var(--space-4) var(--space-5);
    }

    .danger-zone-heading {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--danger-text);
      font-weight: 700;
      margin-bottom: var(--space-2);
    }

    /* Tertiary weight (2026-09 UX Phase 2B): a quiet top divider instead of
       a full bordered .card, for reference/history content that shouldn't
       visually compete with the status/action cards above it on a detail
       page - same concept the Operative mobile app already uses for its
       own "Kilder" section. No background, no border box, just enough
       separation to read as "you've left the important stuff". */
    .section-quiet {
      margin-top: 28px;
      padding-top: 20px;
      border-top: 1px solid var(--border);
    }
    .section-quiet .card-header { margin-bottom: 14px; padding-bottom: 0; border-bottom: none; }

    .card-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 18px;
      padding-bottom: 14px;
      border-bottom: 1px solid var(--border);
      flex-wrap: wrap;
    }

    /* A card-header with nothing below it (a standalone card whose entire
       content IS the header) doesn't need the divider - avoids a stray line
       sitting directly above the card's own bottom edge. */
    .card-header:last-child {
      margin-bottom: 0;
      padding-bottom: 0;
      border-bottom: none;
    }

    .card-header h2,
    .card-header h3 {
      margin: 0;
      font-size: clamp(1rem, 2.4vw, 1.2rem);
      font-weight: 700;
      letter-spacing: -0.01em;
      color: var(--text-primary);
    }

    .status-pill {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      border-radius: 999px;
      padding: 0.32rem 0.75rem;
      font-size: 0.78rem;
      font-weight: 600;
      border: 1px solid;
      white-space: nowrap;
    }

    .status-pill.overdue {
      background: var(--danger-bg);
      border-color: var(--danger-border);
      color: var(--danger);
    }

    .status-pill.due-soon {
      background: var(--warning-bg);
      border-color: var(--warning-border);
      color: var(--warning);
    }

    .status-pill.ok {
      background: var(--success-bg);
      border-color: var(--success-border);
      color: var(--success);
    }

    .status-pill.retired {
      background: var(--neutral-bg);
      border-color: var(--neutral-border);
      color: var(--neutral-text);
    }

    /* Gear's two new PROD-1 states (Phase 6) - .overdue/.due-soon/.ok/.retired
       above are shared by contact-status and deviation-status pills too, so
       they keep their existing meaning unchanged; these two are gear-only. */
    .status-pill.ute-av-tjeneste {
      background: var(--danger-bg);
      border-color: var(--danger-border);
      color: var(--danger);
    }

    .status-pill.avvik-under-oppfolging {
      background: var(--warning-bg);
      border-color: var(--warning-border);
      color: var(--warning);
    }

    /* ---------- Active-filter indicator (Category-Leading UX Sprint 2,
       "the user must understand when filters are active") ---------- */
    .filter-active-bar {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 8px;
      margin-bottom: 14px;
      padding: 8px 12px;
      background: var(--panel-alt);
      border-radius: var(--radius-sm);
      font-size: 0.85rem;
    }

    .filter-active-label { color: var(--text-tertiary); font-weight: 600; }

    .filter-chip {
      display: inline-flex;
      align-items: center;
      padding: 0.2rem 0.65rem;
      border-radius: 999px;
      background: var(--panel-raised);
      border: 1px solid var(--border-strong);
      color: var(--text-secondary);
      font-weight: 600;
      font-size: 0.8rem;
    }

    .filter-active-bar .link { margin-left: auto; }

    .filters {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      align-items: end;
      margin-bottom: 16px;
    }

    .form-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
      gap: 16px;
    }

    .field {
      display: flex;
      flex-direction: column;
      gap: 6px;
    }

    .field.wide {
      grid-column: 1 / -1;
    }

    /* A submit/cancel row that sizes to its buttons and sits at the end of
       the form, rather than a lone button stretched across the whole card -
       full width only comes back below the mobile breakpoint (see @media
       block), where a wide button is the easier target again. */
    .form-actions {
      display: flex;
      flex-direction: row;
      gap: 10px;
      justify-content: flex-end;
      flex-wrap: wrap;
    }

    label {
      font-size: 0.82rem;
      font-weight: 600;
      color: var(--text-secondary);
    }

    input, select, textarea {
      width: 100%;
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-sm);
      background: var(--panel);
      color: var(--text-primary);
      min-height: 44px;
      padding: 0.65rem 0.85rem;
      font: inherit;
      transition: border-color 0.12s ease, box-shadow 0.12s ease;
    }

    input::placeholder, select::placeholder, textarea::placeholder {
      color: var(--text-tertiary);
    }

    input[type="checkbox"], input[type="radio"] {
      width: 18px;
      height: 18px;
      min-height: 0;
      accent-color: var(--brand-text);
      cursor: pointer;
      flex-shrink: 0;
    }

    /* The native file-picker button ignores most input styling by default
       and stays browser-chrome light-grey regardless of theme - both
       standard and WebKit-prefixed selectors are needed for full coverage. */
    input[type="file"] {
      padding: 0.5rem 0.65rem;
      cursor: pointer;
    }

    input[type="file"]::file-selector-button,
    input[type="file"]::-webkit-file-upload-button {
      background: var(--panel-raised);
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-sm);
      color: var(--text-primary);
      font: inherit;
      font-weight: 600;
      padding: 0.5rem 0.9rem;
      margin-right: 12px;
      cursor: pointer;
      transition: background-color var(--motion-fast) ease;
    }

    input[type="file"]::file-selector-button:hover,
    input[type="file"]::-webkit-file-upload-button:hover {
      background: var(--panel-alt);
    }

    textarea {
      min-height: 100px;
      resize: vertical;
    }

    input:focus, select:focus, textarea:focus {
      outline: none;
      border-color: var(--brand-text);
      box-shadow: 0 0 0 3px var(--brand-soft);
    }

    table {
      width: 100%;
      border-collapse: collapse;
      table-layout: auto;
    }

    th, td {
      text-align: left;
      padding: 0.85rem 0.8rem;
      border-bottom: 1px solid var(--border);
      vertical-align: middle;
      overflow-wrap: anywhere;
    }

    th {
      font-size: 0.72rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--text-tertiary);
      background: transparent;
      font-weight: 700;
    }

    tbody tr {
      transition: background-color 0.1s ease;
    }

    tbody tr:hover {
      background: var(--panel-alt);
    }

    .link {
      color: var(--brand-text);
      font-weight: 600;
      cursor: pointer;
      text-underline-offset: 2px;
    }

    .link:hover {
      text-decoration: underline;
    }

    .empty-state {
      display: grid;
      place-items: center;
      text-align: center;
      min-height: 200px;
      border: 1.5px dashed var(--border-strong);
      border-radius: var(--radius);
      background: var(--panel-alt);
      color: var(--text-secondary);
      padding: 2rem;
    }

    .empty-state strong {
      display: block;
      color: var(--text-primary);
      font-size: 1.05rem;
      margin-bottom: 6px;
    }

    .detail-layout {
      display: grid;
      grid-template-columns: minmax(240px, 300px) minmax(0, 1fr);
      gap: 20px;
    }

    /* When there's no photo card, the remaining column would otherwise land
       in the narrow 300px track by grid auto-placement, leaving a large dead
       gap where the photo would have been - span both tracks and center
       instead, matching the width other single-column detail cards use. */
    .detail-layout .detail-main-only {
      grid-column: 1 / -1;
      max-width: 640px;
      margin: 0 auto;
      width: 100%;
    }

    .qr-card {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 14px;
      text-align: center;
    }

    .gear-card-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
      gap: 16px;
    }

    .gear-card {
      display: flex;
      flex-direction: column;
      gap: 12px;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--panel);
      padding: 1.1rem;
      box-shadow: var(--shadow-sm);
    }

    .gear-card-top {
      display: flex;
      gap: 12px;
      align-items: flex-start;
    }

    .gear-card-title { font-weight: 700; color: var(--text-primary); font-size: 0.95rem; }
    .gear-card-sub { font-size: 0.8rem; color: var(--text-tertiary); margin-top: 2px; }

    .gear-card-deviation {
      display: flex;
      gap: 10px;
      align-items: center;
      background: var(--warning-bg);
      border: 1px solid var(--warning-border);
      border-radius: var(--radius-sm);
      padding: 0.6rem 0.7rem;
      font-size: 0.82rem;
      color: var(--warning);
    }

    .gear-card-deviation img {
      width: 40px;
      height: 40px;
      object-fit: cover;
      border-radius: 6px;
      flex-shrink: 0;
    }

    /* Base (desktop-first) state for the Alt utstyr register's mobile card
       view - hidden here, switched on inside the @media(max-width:768px)
       block below. Must stay earlier in source order than that block. */
    .register-cards {
      display: none;
    }

    .meta-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
      gap: 10px;
      margin-top: 18px;
    }

    .meta-item {
      background: var(--panel-alt);
      border: 1px solid var(--border);
      border-radius: var(--radius-sm);
      padding: 0.85rem 1rem;
    }

    .meta-label {
      display: block;
      color: var(--text-tertiary);
      font-size: 0.7rem;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      margin-bottom: 4px;
      font-weight: 700;
    }

    .meta-value {
      font-size: 1rem;
      font-weight: 600;
      color: var(--text-primary);
    }

    .profile-hero {
      display: grid;
      grid-template-columns: 1fr minmax(300px, 1fr);
      gap: 28px;
      align-items: center;
      margin-bottom: 28px;
    }

    .profile-logo {
      width: 100%;
      max-width: 400px;
      height: 240px;
      border-radius: var(--radius);
      background: var(--panel-alt);
      border: 1px solid var(--border);
      display: grid;
      place-items: center;
      overflow: hidden;
      font-size: 3rem;
    }

    .profile-logo img {
      width: 100%;
      height: 100%;
      /* contain, not cover: a logo needs to be shown whole, not cropped to fit
         the box. A square badge-style logo (like the seeded demo one) in this
         wide, landscape-shaped container would otherwise have its top and
         bottom sliced off. */
      object-fit: contain;
      padding: 16px;
    }

    .profile-info h2 {
      margin: 0 0 6px;
      font-size: 1.8rem;
      font-weight: 700;
      color: var(--text-primary);
    }

    .profile-info p {
      margin: 0;
      color: var(--text-secondary);
      font-size: 1rem;
    }

    .wide { grid-column: 1 / -1; }

    .result-picker {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 10px;
    }

    .result-option {
      position: relative;
    }

    .result-option input {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      margin: 0;
      opacity: 0;
      cursor: pointer;
    }

    .result-option label {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 4px;
      min-height: 72px;
      padding: 0.75rem;
      border-radius: var(--radius);
      border: 1.5px solid var(--border-strong);
      background: var(--panel);
      color: var(--text-secondary);
      font-weight: 600;
      font-size: 0.88rem;
      text-align: center;
      cursor: pointer;
      transition: all 0.12s ease;
    }

    .result-option input:focus-visible + label {
      outline: 2px solid var(--brand);
      outline-offset: 2px;
    }

    .result-option.godkjent input:checked + label {
      border-color: var(--success);
      background: var(--success-bg);
      color: var(--success);
    }

    .result-option.avvik input:checked + label {
      border-color: var(--warning);
      background: var(--warning-bg);
      color: var(--warning);
    }

    .result-option.kassert input:checked + label {
      border-color: var(--danger);
      background: var(--danger-bg);
      color: var(--danger);
    }

    .search-input {
      position: relative;
      flex: 1;
      min-width: 220px;
    }

    .search-input input {
      padding-left: 2.4rem;
    }

    .search-input svg {
      position: absolute;
      left: 0.8rem;
      top: 50%;
      transform: translateY(-50%);
      color: var(--text-tertiary);
      pointer-events: none;
    }

    /* ---------- Stations meter ---------- */

    .station-bar-track {
      width: 100%;
      display: flex;
      height: 10px;
      border-radius: 999px;
      overflow: hidden;
      background: var(--neutral-bg);
    }

    .station-bar-segment { height: 100%; }

    /* ---------- Control Home: attention summary ----------
       Category-Leading UX Sprint 2 - the dominant "what requires
       attention" statement, using only already-computed, authoritative
       counts (never a new aggregation query, never L3 logic). Calm/quiet
       when zero (Sprint 1's "Ready is quiet" principle applied at the
       organization level, not just per-item); Level-4 critical surface
       when not. */
    .control-attention-banner {
      display: flex;
      align-items: center;
      gap: var(--space-4);
      padding: var(--space-5) var(--space-6);
      border-radius: var(--radius-lg);
      margin-bottom: var(--space-6);
    }

    .control-attention-banner.is-quiet {
      background: var(--panel);
      border: 1px solid var(--border);
    }

    .control-attention-banner.is-active {
      background: var(--pvura-surface-critical);
      border: 1px solid var(--danger-border);
      border-left: 3px solid var(--danger-solid);
    }

    .control-attention-headline {
      font-family: var(--font-display);
      font-size: clamp(1.4rem, 2.6vw, 1.9rem);
      font-weight: 800;
      letter-spacing: -0.01em;
      color: var(--text-primary);
      margin: 0;
    }

    .control-attention-breakdown {
      display: flex;
      flex-wrap: wrap;
      gap: 6px 18px;
      margin-top: 6px;
      font-size: 0.88rem;
      color: var(--text-secondary);
    }

    .control-attention-breakdown a { color: inherit; }
    .control-attention-breakdown a:hover { color: var(--text-primary); text-decoration: underline; }

    /* PVURA L3 reason chips - visual escalation per readiness.REASON_SEVERITY
       (blocking/attention/upcoming), never a flat undifferentiated list.
       Text + tone together, matching the status-pill discipline - never
       color alone (the label itself always states the actual condition). */
    .reason-chip {
      display: inline-flex;
      align-items: center;
      padding: 0.25rem 0.7rem;
      border-radius: 999px;
      font-weight: 600;
      font-size: 0.85rem;
      border: 1px solid;
    }
    .reason-chip.tone-blocking { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger); }
    .reason-chip.tone-attention { background: var(--warning-bg); border-color: var(--warning-border); color: var(--warning); }
    .reason-chip.tone-upcoming { background: var(--panel-alt); border-color: var(--border-strong); color: var(--text-secondary); }

    /* PVURA Evidence Engine report tables (readiness_snapshot*.html) -
       deliberately NOT .register-table: that class is a marker paired
       with .register-cards for the equipment register's mobile card-
       swap (display:none below the phone breakpoint, see that rule's
       own comment), and these report tables ship no .register-cards
       fallback markup - reusing .register-table here silently hid the
       whole table below that breakpoint with nothing replacing it
       (found in this mission's own mobile/tablet visual QA). These
       tables are small enough (4-7 columns) to stay simple horizontal-
       scroll-in-place at every width instead. */
    .report-table {
      overflow-x: auto;
    }
    /* Without a min-width, the global table{width:100%} + th,td{overflow-
       wrap:anywhere} rules squeeze every column down to fit the viewport
       instead of the wrapper actually scrolling - found in the same
       mobile/tablet visual QA pass above. min-width forces the table to
       keep a legible column width and hand off to the wrapper's
       overflow-x:auto instead. */
    .report-table table {
      min-width: 640px;
    }

    /* Reason line inside an attention-list row (Krever handling i dag,
       Avvik, Kontroller) - the same "why" the Passport's State/Reason/
       Action stack already carries, extended into list rows rather than
       requiring a click into the Passport to learn it. */
    .attention-item-reason {
      display: block;
      font-size: 0.8rem;
      color: var(--danger-text);
      margin-top: 2px;
    }

    /* ---------- "I dag": hero ring + prioritized action list ---------- */

    .hero-ring-section {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 32px;
      margin-bottom: 32px;
      /* Premium Product Experience mission, Section 16: the dashboard's
         own state-at-a-glance figure gets a real surface and real
         breathing room - previously this floated directly on the page
         background, reading as a loose row of stats rather than one
         deliberate control-overview block. Same surface step every
         other grouped stat area in this design system already uses. */
      padding: 28px 32px;
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
    }

    .hero-ring-figure { flex-shrink: 0; }

    .hero-ring-value {
      font-size: 2.1rem;
      font-weight: 800;
      fill: var(--text-primary);
    }

    .hero-ring-label {
      font-size: 0.7rem;
      font-weight: 700;
      letter-spacing: 0.04em;
      fill: var(--text-tertiary);
      text-transform: uppercase;
    }

    .hero-substats {
      display: flex;
      flex-wrap: wrap;
      gap: 20px 36px;
    }

    /* Premium Product Experience mission, Section 16: each figure reads as
       its own number first, label second ("311 KLARE" as a confident
       statement, not a caption) - same real counts as before, no new
       metric invented, just given the typographic weight a control-
       overview hero figure needs instead of blending into body text. */
    .hero-substat {
      display: flex;
      flex-direction: column;
      gap: 2px;
      font-size: 0.78rem;
      font-weight: 600;
      letter-spacing: 0.03em;
      text-transform: uppercase;
      color: var(--text-tertiary);
    }

    .hero-substat strong {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--text-primary);
      font-size: 2rem;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      letter-spacing: -0.01em;
      text-transform: none;
    }

    .hero-substat-dot {
      width: 10px;
      height: 10px;
      border-radius: 50%;
      flex-shrink: 0;
    }

    .today-list {
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .today-item {
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--panel);
      overflow: hidden;
      transition: opacity 200ms ease, transform 200ms ease, max-height 220ms ease, margin 220ms ease;
      max-height: 400px;
    }

    .today-item:hover { border-color: var(--border-strong); }

    .today-item.leaving {
      opacity: 0;
      transform: translateX(6px);
      max-height: 0;
      margin: 0;
      border-width: 0;
    }

    .today-item-main {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 0.9rem 1.1rem;
      flex-wrap: wrap;
    }

    .today-item-info { flex: 1; min-width: 180px; }
    .today-item-title { font-weight: 700; color: var(--text-primary); font-size: 0.95rem; }
    .today-item-sub { font-size: 0.82rem; color: var(--text-tertiary); margin-top: 2px; }

    .today-quicklog {
      display: none;
      padding: 0 1.1rem 1.1rem;
      border-top: 1px solid var(--border);
      padding-top: 14px;
      margin-top: 2px;
    }

    .today-quicklog[hidden] { display: none; }
    .today-quicklog:not([hidden]) { display: block; }

    .result-picker-compact {
      grid-template-columns: repeat(3, 1fr);
      margin-bottom: 12px;
    }

    .result-picker-compact .result-option label {
      min-height: 52px;
      padding: 0.5rem;
      font-size: 0.8rem;
    }

    .today-quicklog-row {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
    }

    .today-quicklog-row input { flex: 1; min-width: 160px; }

    .today-empty-state {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 1.4rem 1.5rem;
      border: 1px solid var(--success-border);
      background: var(--success-bg);
      border-radius: var(--radius);
      color: var(--success-text);
    }

    .today-empty-state svg { flex-shrink: 0; }
    .today-empty-state strong { display: block; color: var(--text-primary); font-size: 1rem; }
    .today-empty-state span { color: var(--text-secondary); font-size: 0.9rem; }

    /* ---------- Stations: per-station compliance card ---------- */

    .station-card {
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 12px;
      background: var(--panel);
    }

    .station-card-stat {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 8px;
      font-size: 0.88rem;
      color: var(--text-secondary);
    }

    .station-card-stat strong { color: var(--text-primary); font-size: 1rem; }
    .station-card-pct { font-weight: 700; color: var(--text-primary); }

    @media (max-width: 480px) {
      .result-picker {
        grid-template-columns: 1fr;
      }
    }

    /* ---------- Toast ---------- */

    .toast-root {
      position: fixed;
      left: 50%;
      bottom: 22px;
      transform: translateX(-50%);
      z-index: 1000;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;
      pointer-events: none;
    }

    .toast {
      background: var(--text-primary);
      color: var(--panel);
      padding: 0.7rem 1.15rem;
      border-radius: var(--radius);
      box-shadow: var(--shadow-md);
      font-size: 0.86rem;
      font-weight: 600;
      opacity: 0;
      transform: translateY(8px);
      transition: opacity 200ms ease, transform 200ms ease;
      max-width: min(360px, calc(100vw - 40px));
      text-align: center;
    }

    .toast.show { opacity: 1; transform: translateY(0); }
    .toast.toast-error { background: var(--danger-solid); }

    /* ---------- Soft page-load transition ---------- */

    body { animation: pageFadeIn 180ms ease; }

    @keyframes pageFadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    @media (prefers-reduced-motion: reduce) {
      body { animation: none; }
      .today-item { transition: none; }
      .toast { transition: none; }
    }

    /* ---------- Welcome / login animation ---------- */

    .welcome-overlay {
      position: fixed;
      inset: 0;
      z-index: 999;
      background: var(--pvura-bg);
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .welcome-overlay.welcome-hide {
      animation: welcomeFadeOut 0.5s ease forwards;
    }

    .welcome-mark {
      width: 92px;
      height: 92px;
      border-radius: 20px;
      overflow: hidden;
      opacity: 0;
      transform: scale(0.25);
      animation: welcomeScaleIn 0.85s cubic-bezier(0.22, 1, 0.36, 1) forwards;
      animation-delay: 0.1s;
    }

    .welcome-mark img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .welcome-mark svg {
      width: 100%;
      height: 100%;
      display: block;
    }

    @keyframes welcomeScaleIn {
      0% { opacity: 0; transform: scale(0.25); }
      65% { opacity: 1; transform: scale(1.12); }
      100% { opacity: 1; transform: scale(1); }
    }

    @keyframes welcomeFadeOut {
      to { opacity: 0; visibility: hidden; }
    }

    @media (prefers-reduced-motion: reduce) {
      .welcome-mark { animation: none; opacity: 1; transform: none; }
      .welcome-overlay.welcome-hide { animation: none; opacity: 0; visibility: hidden; transition: opacity 0.2s ease; }
    }

    @media print {
      .no-print { display: none !important; }
      body { background: #fff; color: #000; }
      .app-shell { display: block; }
      .topbar { position: static; box-shadow: none; border-bottom: 2px solid #000; }
      .card, .stat-card { box-shadow: none; border: 1px solid #999; background: #fff !important; color: #000 !important; }
      th, td { border-bottom: 1px solid #ccc; }
      a { color: #000; }
    }

    @media (max-width: 768px) {
      .topbar-inner {
        min-height: 60px;
        padding: 0 16px;
      }
      .profile-hero {
        grid-template-columns: 1fr;
      }
      .hero {
        flex-direction: column;
      }
      .form-actions {
        flex-direction: column-reverse;
      }
      .form-actions .btn {
        width: 100%;
      }
      .stats {
        grid-template-columns: 1fr;
      }
      .detail-layout {
        grid-template-columns: 1fr;
      }
      .form-grid {
        grid-template-columns: 1fr;
      }
      .meta-grid {
        grid-template-columns: 1fr;
      }
      /* Full register (Alt utstyr): a wide table is fine on a laptop, but
         forces horizontal scrolling on a phone in a garage. Same data,
         same search/filter - just rendered as cards below the breakpoint
         instead of scrolled sideways. See .register-table/.register-cards
         in gear_list.html. The unscoped .register-cards{display:none} base
         rule MUST come before this block in source order, or it wins the
         cascade tie here too and cards never show on mobile. */
      .register-table {
        display: none;
      }
      .register-cards {
        display: grid;
      }
    }
