/* ==================== PRESENTATION LAYER ====================
   Depth, motion and micro-interaction. Loaded LAST so it can refine what the
   feature stylesheets already lay out, without any of them having to know.

   TWO RULES THIS FILE MUST NEVER BREAK, both learned the hard way here:

   1. NOTHING WITH A RESTING STATE OF opacity:0.
      Every entrance below animates FROM transparent using `backwards` fill, so
      the element's natural state is visible. If the animation never gets a
      frame — reduced motion, a paint the browser skips, an element revealed
      inside a display:none parent — the content is still there. The opposite
      construct (opacity:0 + forwards) is what blanked a whole board in the
      reference project, and this project has its own history of it.

   2. NO transform / filter / opacity / backdrop-filter ON AN ANCESTOR OF A
      MODAL. Each creates a stacking context, and every page partial injects its
      dialogs inside .app-shell — that is exactly how every modal in this app
      ended up painted UNDER Bootstrap's z-1050 backdrop. Verified before
      writing this file: all nine modals sit at div-depth 0 in their partial, so
      no card is ever a modal's ancestor and the hover lifts below are safe.
      .main-header may take backdrop-filter because it is sticky chrome and
      contains no dialog.
   ============================================================ */

/* ---------------------------------------------------------------- depth
   One light source, top-left, consistent everywhere. Three layers per shadow —
   a tight contact shadow, a mid diffusion, and a wide ambient — which is what
   separates a surface that looks placed from one that looks pasted on. */
:root {
    --lift-1: 0 1px 2px rgba(17,17,19,.04), 0 2px 6px -1px rgba(17,17,19,.05);
    --lift-2: 0 1px 2px rgba(17,17,19,.04), 0 6px 16px -4px rgba(17,17,19,.09),
              0 12px 32px -12px rgba(17,17,19,.10);
    --lift-3: 0 2px 4px rgba(17,17,19,.05), 0 12px 28px -8px rgba(17,17,19,.13),
              0 28px 60px -20px rgba(17,17,19,.16);
    --lift-gold: 0 4px 14px -4px rgba(178,140,84,.34), 0 10px 30px -12px rgba(178,140,84,.30);
}
:root[data-theme="dark"] {
    --lift-1: 0 1px 2px rgba(0,0,0,.5);
    --lift-2: 0 2px 6px rgba(0,0,0,.5), 0 10px 26px -8px rgba(0,0,0,.55);
    --lift-3: 0 4px 10px rgba(0,0,0,.55), 0 22px 50px -14px rgba(0,0,0,.65);
    --lift-gold: 0 4px 16px -4px rgba(201,165,95,.30), 0 12px 34px -12px rgba(201,165,95,.24);
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --lift-1: 0 1px 2px rgba(0,0,0,.5);
        --lift-2: 0 2px 6px rgba(0,0,0,.5), 0 10px 26px -8px rgba(0,0,0,.55);
        --lift-3: 0 4px 10px rgba(0,0,0,.55), 0 22px 50px -14px rgba(0,0,0,.65);
        --lift-gold: 0 4px 16px -4px rgba(201,165,95,.30), 0 12px 34px -12px rgba(201,165,95,.24);
    }
}

/* -------------------------------------------------------------- entrance
   `backwards` fill and no resting opacity — see rule 1 at the top. */
@keyframes enter    { from { opacity: 0; transform: translateY(10px); } }
@keyframes enterSm  { from { opacity: 0; transform: translateY(6px); } }

.card-panel,
.ag-card,
.po-brand,
.ag-cov,
.ag-spend,
.mr-kpi,
.en-co {
    animation: enter .5s var(--ease-out) backwards;
}

/* Stagger. A grid of eight cards arriving together reads as a page load; the
   same eight arriving 45ms apart reads as the page assembling itself. Capped at
   ten — past that the last card feels late rather than choreographed. */
.mr-kpis > *:nth-child(1), .ag-team > *:nth-child(1), .po-brands > *:nth-child(1) { animation-delay: 0ms; }
.mr-kpis > *:nth-child(2), .ag-team > *:nth-child(2), .po-brands > *:nth-child(2) { animation-delay: 45ms; }
.mr-kpis > *:nth-child(3), .ag-team > *:nth-child(3), .po-brands > *:nth-child(3) { animation-delay: 90ms; }
.mr-kpis > *:nth-child(4), .ag-team > *:nth-child(4), .po-brands > *:nth-child(4) { animation-delay: 135ms; }
.mr-kpis > *:nth-child(5), .ag-team > *:nth-child(5), .po-brands > *:nth-child(5) { animation-delay: 180ms; }
.mr-kpis > *:nth-child(6), .ag-team > *:nth-child(6), .po-brands > *:nth-child(6) { animation-delay: 225ms; }
.mr-kpis > *:nth-child(7), .ag-team > *:nth-child(7), .po-brands > *:nth-child(7) { animation-delay: 270ms; }
.mr-kpis > *:nth-child(8), .ag-team > *:nth-child(8), .po-brands > *:nth-child(8) { animation-delay: 315ms; }
.mr-kpis > *:nth-child(n+9), .ag-team > *:nth-child(n+9), .po-brands > *:nth-child(n+9) { animation-delay: 360ms; }

/* List rows arrive too, but faster and shallower — a table that bounces is a
   table nobody can read while it settles. */
.po-row, .mr-row, .en-row, .ag-find, .ag-day {
    animation: enterSm .34s var(--ease-out) backwards;
}
.po-row:nth-child(2),  .mr-row:nth-child(2)  { animation-delay: 22ms; }
.po-row:nth-child(3),  .mr-row:nth-child(3)  { animation-delay: 44ms; }
.po-row:nth-child(4),  .mr-row:nth-child(4)  { animation-delay: 66ms; }
.po-row:nth-child(5),  .mr-row:nth-child(5)  { animation-delay: 88ms; }
.po-row:nth-child(n+6),.mr-row:nth-child(n+6){ animation-delay: 110ms; }

/* ------------------------------------------------------------ elevation
   Cards rise toward the cursor. 2px and a shadow — enough to feel alive,
   not enough to shift the layout under someone reading. */
.card-panel {
    box-shadow: var(--lift-1);
    transition: transform .2s var(--ease), box-shadow .2s var(--ease),
                border-color .2s ease;
}
.card-panel:hover {
    transform: translateY(-2px);
    box-shadow: var(--lift-2);
    border-color: var(--gold-300);
}
/* The gold hairline on the card grows into the hover. */
.card-panel::before { transition: width .35s var(--ease-out), opacity .25s ease; }
.card-panel:hover::before { width: 68%; }

/* ------------------------------------------------------------ the header
   Frosted, so content scrolling under it stays legible without a hard edge.
   backdrop-filter creates a stacking context — safe here, this is sticky chrome
   with no dialog inside it (rule 2). */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .main-header {
        background: color-mix(in srgb, var(--surface) 82%, transparent);
        -webkit-backdrop-filter: blur(16px) saturate(160%);
        backdrop-filter: blur(16px) saturate(160%);
    }
}

/* ------------------------------------------------------------ the rail
   The icon leads the label in by 1px on hover. It is a tiny thing and it is
   most of why a nav feels responsive rather than static. */
.sidebar-link i { transition: color .15s ease, transform .18s var(--ease-out); }
.sidebar-link:hover:not(.disabled) i { transform: translateX(1px); }
/* The active pill's gold bar wipes in rather than appearing. */
.sidebar-link.active::before { animation: barIn .3s var(--ease-out) backwards; }
@keyframes barIn { from { height: 0; opacity: 0; } }
.sidebar-link.active { box-shadow: inset 0 0 0 1px var(--gold-200); }

/* ----------------------------------------------------------- the button
   A sheen crosses the primary button on hover. One pass, 620ms, and it is
   masked to the button — the effect people read as "expensive". */
.btn-primary { position: relative; overflow: hidden; box-shadow: var(--lift-gold); }
.btn-primary::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(105deg, transparent 38%,
                rgba(255,255,255,.42) 50%, transparent 62%);
    transform: translateX(-120%);
}
.btn-primary:hover::after { animation: sheen .62s var(--ease-out); }
@keyframes sheen { to { transform: translateX(120%); } }
.btn-primary:hover { box-shadow: var(--lift-gold), 0 8px 22px -6px rgba(178,140,84,.42); }

/* --------------------------------------------------------------- figures
   Big numbers are the thing people look at first, so they get real treatment:
   tight tracking, tabular figures so digits do not jitter while they count, and
   a gold rule under the label. */
.hkpi b, .hkpi-chip b, .ag-cov-pct, .ag-spend-nums b, .ag-det-stats b, .po-brand-n {
    font-variant-numeric: tabular-nums;
    letter-spacing: -.025em;
}
.hkpi { position: relative; transition: background .18s ease; }
.hkpi:hover { background: var(--gold-050); }
.hkpi b { transition: color .18s ease; }
.hkpi:hover b { color: var(--gold-700); }

/* ------------------------------------------------------------ selection */
::selection { background: var(--gold-200); color: var(--gold-900); }
:root[data-theme="dark"] ::selection { background: var(--gold-700); color: #fff; }

/* -------------------------------------------------------------- focus
   One ring, gold, everywhere — and it animates out from the control so it
   registers as a response rather than a border appearing. */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    animation: ring .22s var(--ease-out);
}
@keyframes ring { from { outline-offset: 6px; outline-color: transparent; } }

/* ------------------------------------------------------- interactive rows */
.po-row, .mr-row, .en-row {
    transition: background .15s ease, box-shadow .15s ease;
}
.po-row:hover, .mr-row:hover, .en-row:hover {
    box-shadow: inset 3px 0 0 var(--gold-400);
}

/* ---------------------------------------------------------- brand tiles */
.po-brand { transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s ease; }
.po-brand:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.po-brand.on { box-shadow: var(--lift-gold); }

/* --------------------------------------------------------------- modals
   The dialog scales up a hair as it arrives. Bootstrap's own .modal.fade only
   slides, which at 95vw reads as a panel being shoved onto the screen. */
.modal.fade .modal-dialog {
    transform: translateY(14px) scale(.988);
    transition: transform .28s var(--ease-out), opacity .28s ease;
}
.modal.show .modal-dialog { transform: none; }
.modal-content { box-shadow: var(--lift-3); }
/* Warm the scrim very slightly so it does not read as a grey sheet of glass. */
.modal-backdrop.show { background-color: #14120E; opacity: .46; }

/* --------------------------------------------------------------- toasts */
.toast-msg { box-shadow: var(--lift-3); }

/* ------------------------------------------------------------- tooltips */
.tooltip-inner { box-shadow: var(--lift-3); }

/* ------------------------------------------------------ counting numbers
   Set by Motion.countUp() in core.js while a figure animates. The width is
   reserved by tabular-nums above, so nothing reflows as the digits change. */
.is-counting { color: var(--gold-600); }

/* ==================== REDUCED MOTION ====================
   Every animation here is an entrance or a flourish, so all of them simply stop.
   None of these elements has a resting opacity of 0 (rule 1), so there is
   nothing that needs forcing visible — but the assertions stay, because the one
   time that stops being true the failure is an invisible page. */
@media (prefers-reduced-motion: reduce) {
    .card-panel, .ag-card, .po-brand, .ag-cov, .ag-spend, .mr-kpi, .en-co,
    .po-row, .mr-row, .en-row, .ag-find, .ag-day,
    .sidebar-link.active::before, .btn-primary::after, .modal.fade .modal-dialog {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
        animation-delay: 0ms !important;
    }
    .card-panel:hover, .po-brand:hover { transform: none !important; }
    :focus-visible { animation: none !important; }
}
