/* ============================================================
   public/css/login.css — the logged-out page.

   Structure: sticky header, a two-column body (sign-in rail + catalogue) and
   a footer. No media queries in the body region and none should be added —
   the rail and the catalogue wrap on flex-basis, the rail's own two children
   wrap the same way, headings scale with clamp(), the stats grid is auto-fit
   and the tab strip scrolls. A breakpoint here would only fight the measured
   layoutRail() in the page.

   Colours, type and spacing come from theme.css. The one value not in it is
   the lightened gold on the dark footer: --brand-primary fails AA on #1A1714.
   ============================================================ */

*,*::before,*::after{box-sizing:border-box}
/* The tab strip and the result bar are both display:flex and both get toggled
   with the `hidden` attribute. A display rule in a stylesheet beats the UA's
   `[hidden]{display:none}` every time, so hiding them did nothing at all until
   this was here. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
body{margin:0;font-family:var(--font-body);font-size:15px;color:var(--text-primary);background:var(--bg-page);line-height:1.6;-webkit-font-smoothing:antialiased;min-height:100vh;display:flex;flex-direction:column}
h1,h2,h3,h4,h5,h6{margin:0;font-weight:700;line-height:1.25}
p{margin:0}
a{color:var(--brand-primary);text-decoration:none}
a:hover{opacity:.85}

#partner-login-bg{position:fixed;inset:0;z-index:0;background-size:cover;background-position:center;background-repeat:no-repeat;pointer-events:none}
#partner-login-bg[data-partner-bg]::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,color-mix(in srgb,var(--bg-page) 82%,transparent),color-mix(in srgb,var(--bg-page) 92%,transparent))}
:root[data-partner] .login-main,:root[data-partner] .login-bar{position:relative;z-index:1}
/* A partner's client-facing login must not advertise OccultSanctum's own
   reseller programme to the astrologer's clients. brand-boot stamps
   data-partner; invisible on the consumer login. */
:root[data-partner] [data-consumer-only]{display:none}

/* ── HEADER ── */
.login-bar{position:sticky;top:0;z-index:900;background:var(--brand-gradient);box-shadow:0 2px 12px rgba(26,23,20,.25)}
.login-bar-in{max-width:1180px;margin:0 auto;height:54px;padding:0 24px;display:flex;align-items:center;justify-content:space-between;gap:16px}
.login-brand{display:flex;align-items:center;gap:9px;color:#fff;font-size:16px;font-weight:800;letter-spacing:-.3px}
.login-brand:hover{opacity:1}
.login-brand .sigil{font-size:20px}
.login-bar-nav{display:flex;align-items:center;gap:2px}
.login-bar-nav a{font-size:12.5px;font-weight:500;color:rgba(255,255,255,.85);padding:6px 12px;border-radius:var(--radius-sm);white-space:nowrap}
/* The only media query on the page, and it is in the header, not the body
   region the handoff asks to keep breakpoint-free. Measured: the wordmark is
   153px and the two links 279px, so with 48px of padding and the gap the bar
   needs 496px before it starts clipping — and a partner's brand name can be
   longer than "OccultSanctum". The reseller link is the one to drop, at 204px
   the widest thing in the bar and the least relevant to someone signing in; it
   is still in the footer. */
@media (max-width:620px){.login-bar-nav .bar-biz{display:none}}
.login-bar-nav a:hover{background:rgba(255,255,255,.12);color:#fff;opacity:1}

/* ── BODY ──
   The wrap point is flex-basis arithmetic: 356 + 40 gap + 560 + 48 padding.
   layoutRail() measures whether the two ended up on the same line rather than
   guessing that number, because guessing leaves a band where the rail is
   sticky while stacked and pins itself over the catalogue. */
.login-main{flex:1 0 auto;max-width:1180px;width:100%;margin:0 auto;padding:36px 24px 48px}
.login-body{display:flex;flex-wrap:wrap;gap:40px;align-items:flex-start}
/* min-width:0 on every flex item whose basis is wider than a phone. A flex
   item's default min-width is auto, so a 356px basis will not shrink below its
   content inside a 342px content box, and the page scrolls sideways instead of
   reflowing. The catalogue column already had it; the rail and the auth card
   did not. */
.login-rail{flex:1 1 356px;min-width:0;display:flex;flex-wrap:wrap;gap:22px 32px;align-items:flex-start}
.login-headline{flex:1 1 280px;min-width:0}
.rail-eyebrow{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:1.8px;text-transform:uppercase;color:var(--brand-primary);margin-bottom:10px}
.login-headline h1{font-family:var(--font-serif);font-size:clamp(28px,3.4vw,34px);font-weight:600;line-height:1.12;letter-spacing:-.02em;margin-bottom:10px}
.login-headline h1 em{font-style:italic;color:var(--brand-primary)}
.rail-lead{font-size:14px;line-height:1.6;color:var(--text-secondary)}

/* ── AUTH CARD ── */
.auth-card{flex:1 1 340px;min-width:0;max-width:400px;background:var(--bg-card);border-radius:var(--radius-lg);padding:30px 28px;box-shadow:var(--shadow-lg);text-align:center}
.auth-error{display:flex;gap:9px;align-items:flex-start;padding:10px 13px;margin-bottom:20px;background:var(--status-error-bg);border:1px solid color-mix(in srgb,var(--status-error) 30%,transparent);border-radius:var(--radius-md);text-align:left;font-size:12.5px;font-weight:600;color:var(--status-error-hover)}
.auth-error-ico{font-size:13px;color:var(--status-error);line-height:1.4}
.auth-logo{font-size:38px;margin-bottom:10px;line-height:1}
/* Not an <h2>: the five catalogue panels own the page's second level, and
   "Sign In" is a control label, not a section of content. */
.auth-title{font-size:21px;font-weight:700;margin-bottom:3px}
.auth-sub{font-size:13px;color:var(--text-secondary);margin-bottom:24px}
.btn-auth{display:flex;align-items:center;justify-content:center;gap:12px;width:100%;padding:14px;border:1px solid var(--border-medium);border-radius:var(--radius-md);background:var(--bg-card);color:var(--text-primary);font-size:15px;font-weight:600;cursor:pointer;transition:var(--transition-fast);text-decoration:none;font-family:inherit}
.btn-auth:hover{background:var(--bg-elevated);box-shadow:var(--shadow-md);opacity:1}
.btn-auth svg{width:20px;height:20px;flex-shrink:0}
.btn-auth.apple{background:var(--text-primary);color:var(--bg-elevated);border-color:var(--text-primary)}
.btn-auth.apple:hover{opacity:.9}
.btn-auth.apple svg{width:19px;height:19px}
.auth-divider{display:flex;align-items:center;gap:12px;margin:18px 0;color:var(--text-muted);font-size:12px}
.auth-divider::before,.auth-divider::after{content:'';flex:1;height:1px;background:var(--border-light)}
.auth-disclaimer{margin-top:22px;padding:12px;background:var(--bg-elevated);border-radius:var(--radius-md);font-size:12px;color:var(--text-secondary);line-height:1.6;text-align:left}
.auth-legal{margin-top:16px;font-size:12px;color:var(--text-muted);line-height:1.5;text-align:left}
.auth-legal a{color:var(--brand-primary);font-weight:500}

/* ── CATALOGUE ── */
.login-catalogue{flex:1 1 560px;min-width:0}
.cat-head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:18px}
.cat-eyebrow{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:1.8px;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px}
.cat-h{font-family:var(--font-serif);font-size:clamp(22px,2.6vw,27px);font-weight:600;letter-spacing:-.02em}
.cat-search{position:relative;flex:0 1 250px;min-width:190px}
.cat-search input{width:100%;padding:10px 12px 10px 30px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md);font-family:inherit;font-size:13.5px;color:var(--text-primary);outline:none}
.cat-search input:focus{border-color:var(--brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand-primary) 10%,transparent)}
.cat-search-ico{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:13px;color:var(--text-muted);pointer-events:none}

.cat-card{background:var(--bg-card);border:1px solid var(--border-medium);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm)}

/* THE TAB STRIP. Two things here are load-bearing rather than cosmetic.

   overflow-y:hidden — overflow-x:auto makes the UA compute overflow-y:auto on
   the same box, and the active underline sitting at bottom:-1px pushes
   scrollHeight 1px past clientHeight, which renders a vertical scrollbar inside
   the strip and steals ~13px of width.

   The background is a scrolling-shadow stack. Five tabs do not fit a 390px
   phone, and the strip used to end flush at the edge — which reads as "there
   are three tabs" rather than "there are more, scroll", and is how Learn and
   Apps would go unnoticed. The cover gradients are painted in the LOCAL
   coordinate system so they travel with the content and mask the shadow once
   that end is reached; the shadows are painted against the SCROLL box so they
   stay pinned to the edges. Nothing shows when everything fits. */
.cat-tabs{display:flex;padding:0 6px;border-bottom:1px solid var(--border-medium);overflow-x:auto;overflow-y:hidden;
  background:
    linear-gradient(to right,var(--bg-card-hover),transparent) 0 0/18px 100% no-repeat local,
    linear-gradient(to left,var(--bg-card-hover),transparent) 100% 0/18px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%,color-mix(in srgb,var(--text-primary) 16%,transparent),transparent) 0 0/14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%,color-mix(in srgb,var(--text-primary) 16%,transparent),transparent) 100% 0/14px 100% no-repeat scroll,
    var(--bg-card-hover)}
.cat-tab{flex-shrink:0;border:0;background:transparent;padding:14px 16px;font-family:inherit;font-size:13px;color:var(--text-secondary);display:flex;align-items:center;gap:7px;white-space:nowrap;position:relative;cursor:pointer}
.cat-tab-label{font-weight:600}
.cat-tab-count{font-family:var(--font-mono);font-size:10.5px;color:var(--text-muted)}
.cat-tab:hover{color:var(--text-primary)}
.cat-tab.is-on{color:var(--brand-primary)}
.cat-tab.is-on .cat-tab-label{font-weight:700}
.cat-tab-rule{position:absolute;left:14px;right:14px;bottom:-1px;height:2px;background:var(--brand-primary);border-radius:2px}

/* Every panel is in the DOM; four of five are [hidden] at any moment. */
.cat-panel[hidden]{display:none}
/* The panel heading is for the outline and for a crawler. On screen the tab
   above it already says the same word, so it is not repeated visually. */
.cat-panel-h{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.cat-row{display:flex;width:100%;text-align:left;align-items:center;gap:15px;padding:15px 20px;border:0;border-bottom:1px solid var(--bg-code);background:transparent;font-family:inherit;cursor:pointer;transition:background .12s ease}
.cat-row:last-child{border-bottom:0}
.cat-row:hover{background:var(--bg-card-hover)}
.cat-row:focus-visible{outline:2px solid var(--brand-primary);outline-offset:-2px}
.cat-mg{flex-shrink:0;width:38px;height:38px;border-radius:9px;background:color-mix(in srgb,var(--brand-primary) 8%,transparent);color:var(--brand-primary);font-family:var(--font-mono);font-size:11px;font-weight:700;letter-spacing:.5px;display:flex;align-items:center;justify-content:center}
.cat-main{flex:1 1 auto;min-width:0}
.cat-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cat-name{font-size:15px;font-weight:700;color:var(--text-primary)}
.cat-chip{font-family:var(--font-mono);font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-full);background:var(--bg-badge);border:1px solid var(--border-medium);color:var(--text-secondary)}
.cat-aud{display:block;font-size:10px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;color:var(--brand-primary)}
.cat-one{display:block;font-size:13px;color:var(--text-secondary);line-height:1.5;margin-top:2px}
.cat-cta{flex-shrink:0;white-space:nowrap;font-size:12px;font-weight:700;color:var(--brand-primary)}
.cat-soon{flex-shrink:0;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted)}
.cat-soon::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--brand-secondary)}
/* ── THE CLAMP ──
   A panel that would run to 54 rows shows 8 and offers the rest. The surplus is
   still in the markup — hiding it is purely visual, which is what keeps the two
   audiences from fighting: a crawler and a no-JS visitor need every item on the
   page (the entire reason this catalogue is server-rendered), and a human needs
   about eight to decide whether to sign in.

   Scoped to .js, set by an inline script in the head. Without it the clamp
   never applies and the control is not shown, so nothing here can strand
   content behind a button that will not run. The server emits the clamped
   markup directly rather than the page adding it on hydration, so the catalogue
   does not visibly collapse a beat after the page paints.

   Two selectors because the two panel shapes nest differently: rows are direct
   children of .cat-rows, cards are children of a grid inside it. */
.js .cat-panel.is-clamped .cat-rows>:nth-child(n+9),
.js .cat-panel.is-clamped .oracle-row>:nth-child(n+7),
.js .cat-panel.is-clamped .app-row>:nth-child(n+7){display:none}
/* A phone shows one card per row, and a card is ~235px there against a 71px
   row, so six of them is a wall. Smaller budget on a narrow screen.
   This only ever TIGHTENS a panel the server already clamped, so it can never
   hide an item that has no button to reveal it — a panel under the renderer's
   threshold carries no .is-clamped and none of this applies to it. */
@media (max-width:600px){
  .js .cat-panel.is-clamped .cat-rows>:nth-child(n+7),
  .js .cat-panel.is-clamped .oracle-row>:nth-child(n+5),
  .js .cat-panel.is-clamped .app-row>:nth-child(n+5){display:none}
}
.cat-more{display:none}
.js .cat-more{display:block;width:100%;border:0;border-top:1px solid var(--bg-code);background:transparent;padding:14px 20px;font-family:inherit;font-size:12.5px;font-weight:700;color:var(--brand-primary);text-align:left;cursor:pointer}
.js .cat-more:hover{background:var(--bg-card-hover)}
.js .cat-more:focus-visible{outline:2px solid var(--brand-primary);outline-offset:-2px}
.cat-more-t::after{content:' \2193';font-weight:400}
.cat-more[aria-expanded="true"] .cat-more-t::after{content:' \2191'}
/* The grids carry the panel's inset as padding, so a clamped card panel would
   put its button 20px away from the cards above it and flush against the note
   below. Pull it up to sit on the divider the row panels give it for free. */
.js #panel-oracles .cat-more,.js #panel-apps .cat-more{margin-top:-20px}

.cat-note{padding:13px 20px;font-size:12px;color:var(--text-muted);font-style:italic}
.cat-foot{margin-top:14px;font-size:12px;color:var(--text-muted);line-height:1.55}

.cat-resultbar{padding:13px 20px;border-bottom:1px solid var(--border-medium);background:var(--bg-card-hover);display:flex;align-items:center;justify-content:space-between;gap:14px;font-size:13px;color:var(--text-secondary)}
.cat-resultbar strong{color:var(--text-primary);font-weight:700}
.cat-clear{border:0;background:transparent;font-family:inherit;font-size:12.5px;font-weight:700;color:var(--brand-primary);cursor:pointer}
.cat-empty{padding:40px 20px;text-align:center}
.cat-empty-h{font-family:var(--font-serif);font-size:22px;font-weight:600;margin-bottom:6px}
.cat-empty p{font-size:13.5px;color:var(--text-secondary)}
.cat-empty em{font-style:italic}

/* ── LEARN PANEL ── */
.learn-block{padding:26px 22px}
.learn-block .cat-eyebrow{color:var(--brand-primary);letter-spacing:1.6px}
.learn-block h3{font-family:var(--font-serif);font-size:24px;font-weight:600;letter-spacing:-.02em;margin-bottom:8px}
.learn-block-lead{font-size:13.5px;color:var(--text-secondary);line-height:1.65;max-width:62ch;margin-bottom:18px}
.learn-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:12px;margin-bottom:16px}
.learn-stat{padding:14px 16px;background:var(--accent-surface);border:1px solid color-mix(in srgb,var(--brand-primary) 14%,transparent);border-radius:var(--radius-md)}
.learn-stat-v{display:block;font-size:22px;font-weight:800;color:var(--brand-primary);line-height:1.2}
.learn-stat-l{display:block;font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--text-muted)}
.learn-ladder-strip{padding:13px 16px;background:color-mix(in srgb,var(--brand-primary) 4%,transparent);border-left:3px solid var(--brand-primary);border-radius:var(--radius-md);margin-bottom:16px}
.learn-ladder-tiers{display:flex;flex-wrap:wrap;align-items:center;gap:7px}
.learn-tier{font-size:13px;font-weight:700;color:var(--brand-primary)}
.learn-tier-sep{font-size:12px;color:var(--text-muted)}
.learn-ladder-note{display:block;margin-top:6px;font-size:13px;color:var(--text-secondary)}
.learn-list{list-style:none;margin:0 0 18px;padding:0;font-size:13px;color:var(--text-secondary);line-height:1.7}
.learn-list strong{color:var(--text-primary)}
/* Each programme links to its own page — the one thing the panel lacked before
   it briefly became a band, and kept when it came back. */
.learn-list a{font-weight:700;color:var(--text-primary)}
.learn-list a:hover{color:var(--brand-primary);opacity:1}
.learn-cta{display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.btn-gold{display:inline-block;padding:12px 24px;background:var(--brand-primary);color:var(--text-inverse);border-radius:var(--radius-md);font-size:13.5px;font-weight:600;transition:var(--transition-fast)}
.btn-gold:hover{background:var(--brand-primary-hover);opacity:1}
.link-gold{font-size:13.5px;font-weight:700;color:var(--brand-primary)}

/* ── FOOTER ── */
.login-foot{flex-shrink:0;background:var(--bg-sidebar,#1A1714);padding:26px 24px 30px}
.login-foot-in{max-width:1180px;margin:0 auto}
.login-foot-top{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:24px}
.login-foot-biz{min-width:240px}
/* --brand-primary fails AA on this background; this is a lightened gold and
   the one colour on the page not taken from theme.css. */
.login-foot-biz a{font-size:13.5px;font-weight:700;color:#C9A227}
.login-foot-biz p{margin-top:6px;font-size:12.5px;color:rgba(248,247,244,.5);line-height:1.6;max-width:52ch}
.login-foot-badges{display:flex;align-items:center;gap:9px}
.login-foot-badges img{display:block;height:40px;width:auto}
.login-foot-bottom{margin-top:20px;padding-top:18px;border-top:1px solid rgba(248,247,244,.12);display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between}
.login-foot-bottom nav{display:flex;gap:16px}
.login-foot-bottom a{font-size:12.5px;color:rgba(248,247,244,.55)}
.login-foot-copy{font-size:12.5px;color:rgba(248,247,244,.35)}

/* ── DETAIL MODAL ──
   Production's component, reused. What changed is what opens it (a row, not a
   "More details" link inside a long card) and the footer CTA row. */
.about-overlay{position:fixed;inset:0;z-index:2000;background:rgba(26,23,20,.55);backdrop-filter:blur(3px);display:none;align-items:flex-start;justify-content:center;padding:24px;overflow-y:auto}
.about-overlay.open{display:flex;animation:ovIn .16s ease}
@keyframes ovIn{from{opacity:0}to{opacity:1}}
.about-card{position:relative;width:100%;max-width:640px;margin:auto;background:var(--bg-card);border:1px solid var(--border-medium);border-radius:var(--radius-xl);box-shadow:0 24px 70px rgba(26,23,20,.28);padding:38px 34px;animation:cardIn .2s ease}
@keyframes cardIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.about-overlay.open,.about-card{animation:none}}
.about-close{position:absolute;top:16px;right:16px;width:34px;height:34px;border-radius:var(--radius-full);border:1px solid var(--border-light);background:var(--bg-page);color:var(--text-secondary);font-size:19px;line-height:1;cursor:pointer;transition:var(--transition-fast)}
.about-close:hover{color:var(--text-primary);border-color:var(--brand-primary)}
.about-head{text-align:center;margin-bottom:6px}
.about-name{font-family:var(--font-serif);font-size:clamp(27px,4vw,35px);font-weight:600;color:var(--text-primary);line-height:1.06;letter-spacing:-.02em}
.about-tag{font-family:var(--font-serif);font-style:italic;font-size:18px;color:var(--brand-primary);margin-top:6px}
.about-intro{text-align:center;max-width:46ch;margin:16px auto 26px;font-size:14.5px;color:var(--text-secondary);line-height:1.65}
.about-intro:empty{display:none}
.about-sec{margin-bottom:20px}
.about-sec h4{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;color:var(--brand-primary);margin:0 0 8px}
.about-sec p{margin:0;font-size:14px;color:var(--text-secondary);line-height:1.7}
.about-sec ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.about-sec li{position:relative;padding-left:20px;font-size:14px;color:var(--text-secondary);line-height:1.55}
.about-sec li::before{content:'';position:absolute;left:0;top:8px;width:6px;height:6px;border-radius:50%;background:var(--brand-primary)}
.about-foot{margin-top:24px;padding-top:20px;border-top:1px solid var(--border-light);display:flex;flex-wrap:wrap;align-items:center;gap:14px;font-size:13.5px;font-weight:700}
.about-foot:empty{display:none}
.about-soon{display:inline-flex;align-items:center;gap:7px;font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted)}
.about-soon::before{content:'';width:7px;height:7px;border-radius:50%;background:var(--brand-secondary)}
@media(max-width:560px){.about-card{padding:30px 20px}.about-overlay{padding:12px}}

/* ── ITEM PAGE ──
   /reports/<slug> and /learn/<slug>. Shares this page's chrome (header,
   footer, modal-free) so the two never drift apart visually, and reuses the
   catalogue's type scale rather than inventing a second one. */
.item-body{flex:1 0 auto;max-width:820px;width:100%;margin:0 auto;padding:28px 24px 48px}
.item-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:12.5px;color:var(--text-muted);margin-bottom:18px}
.item-crumbs a{color:var(--brand-primary);font-weight:600}
.item-card{background:var(--bg-card);border:1px solid var(--border-medium);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);padding:34px 30px}
.item-head{margin-bottom:22px}
.item-kicker{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:1.8px;text-transform:uppercase;color:var(--brand-primary);margin-bottom:10px}
.item-card h1{font-family:var(--font-serif);font-size:clamp(28px,4vw,38px);font-weight:600;line-height:1.1;letter-spacing:-.02em}
.item-tagline{font-family:var(--font-serif);font-style:italic;font-size:18px;color:var(--brand-primary);margin-top:8px}
.item-tagline:empty{display:none}
.item-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:24px}
.item-facts:empty{display:none}
.item-fact{padding:13px 15px;background:var(--accent-surface);border:1px solid color-mix(in srgb,var(--brand-primary) 14%,transparent);border-radius:var(--radius-md)}
.item-fact dt{font-size:10px;font-weight:700;letter-spacing:.9px;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px}
.item-fact dd{margin:0;font-size:14px;font-weight:600;color:var(--text-primary);display:flex;flex-wrap:wrap;align-items:center;gap:5px}
.item-prose{font-size:15px;color:var(--text-secondary);line-height:1.75;display:flex;flex-direction:column;gap:14px}
.item-prose:empty{display:none}
.item-cta{margin-top:26px;padding-top:22px;border-top:1px solid var(--border-light);display:flex;flex-wrap:wrap;align-items:center;gap:18px}
.item-note{flex-basis:100%;font-size:12px;color:var(--text-muted)}
.item-more{margin-top:32px}
.item-more:empty{display:none}
.item-more h2{font-family:var(--font-serif);font-size:22px;font-weight:600;letter-spacing:-.02em;margin-bottom:14px}
.item-more-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px}
.item-more-list li{background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md);padding:13px 15px}
.item-more-list a{font-size:14px;font-weight:700;color:var(--text-primary)}
.item-more-list a:hover{color:var(--brand-primary);opacity:1}
.item-more-list span{display:block;margin-top:3px;font-size:12.5px;color:var(--text-secondary);line-height:1.5}

/* ── BELOW THE FOLD ──
   Two bands under the catalogue, full width of the content rail. They sit
   outside the two-column flex row, so they need their own width and their own
   top margin rather than inheriting the body's gap. */
.band{margin-top:56px}
.band:empty{display:none}
.band-h{font-family:var(--font-serif);font-size:clamp(22px,2.6vw,28px);font-weight:600;letter-spacing:-.02em;margin-bottom:8px}

/* ── OBJECTIONS + FAQ ── */
/* Four items, so a wide enough minimum to land 2x2 rather than 3+1 — at 260px
   the auto-fit gives three columns on a desktop and orphans the fourth.
   min(400px,100%) rather than a bare 400px: a grid track has no obligation to
   fit its container, so on a 390px phone the bare value made the whole DOCUMENT
   34px wider than the viewport and the page scrolled sideways. */
.claims{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(400px,100%),1fr));gap:18px}
.claim{padding:20px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md)}
.claim h3{font-size:15px;font-weight:700;line-height:1.35;margin-bottom:7px}
.claim h3::before{content:'✓';display:inline-block;margin-right:8px;color:var(--brand-primary);font-weight:800}
.claim p{font-size:13px;color:var(--text-secondary);line-height:1.65}

/* <details> rather than a script: the answers are in the markup either way,
   which is what a crawler reads, and the page needs no JavaScript to open one. */
.faq{background:var(--bg-card);border:1px solid var(--border-medium);border-radius:var(--radius-lg);overflow:hidden;box-shadow:var(--shadow-sm)}
.faq-q{border-bottom:1px solid var(--bg-code)}
.faq-q:last-child{border-bottom:0}
.faq-q>summary{list-style:none;cursor:pointer;padding:15px 20px;font-size:14.5px;font-weight:700;color:var(--text-primary);display:flex;align-items:center;justify-content:space-between;gap:14px}
.faq-q>summary::-webkit-details-marker{display:none}
.faq-q>summary::after{content:'+';flex-shrink:0;font-family:var(--font-mono);font-size:16px;font-weight:700;color:var(--brand-primary);line-height:1}
.faq-q[open]>summary::after{content:'−'}
.faq-q>summary:hover{background:var(--bg-card-hover)}
.faq-q>p{padding:0 20px 17px;font-size:13.5px;color:var(--text-secondary);line-height:1.7;max-width:78ch}

/* ── THE CARD PANELS: AI CONSULTANTS AND APPS ──
   Both are catalogue tabs like the rest, but their panels draw cards instead of
   one-line rows, because what decides an oracle is its blurb and its cost and
   what decides an app is the store badge — none of which fits on a line.

   A row panel is edge-to-edge — each row carries its own padding and its own
   divider, and touching the card's border is the point. Cards are not: without
   an inset they sit flush against .cat-card, whose overflow:hidden then clips
   their own rounded corners. It goes on the panel body rather than on the grid
   so that the "coming soon" line under the grid is inside it too. */
#panel-oracles .cat-rows,#panel-apps .cat-rows{padding:20px}
.oracle-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px}
.oracle-c{padding:20px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:11px}
.oracle-c-top{display:flex;align-items:flex-start;gap:12px}
.oracle-c-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:color-mix(in srgb,var(--brand-primary) 8%,transparent);display:flex;align-items:center;justify-content:center;font-size:19px}
.oracle-c h3{font-size:16px;font-weight:700;line-height:1.3}
.oracle-c-cost{display:block;margin-top:2px;font-family:var(--font-mono);font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--brand-primary)}
.oracle-c-desc{font-size:13px;color:var(--text-secondary);line-height:1.6;flex:1 1 auto}
/* Tags and requirements on one line. Two strips stacked cost ~30px a card and
   read as two facts when they are one: what it covers, what it wants from you.
   They wrap to two lines only when the tags genuinely fill the row. */
.oracle-c-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.oracle-c-tags{display:flex;flex-wrap:wrap;gap:5px}
.oracle-c-tags span{padding:3px 10px;border-radius:var(--radius-full);background:color-mix(in srgb,var(--brand-primary) 6%,transparent);color:var(--brand-primary);font-size:11px;font-weight:600}
/* No margin-left:auto. It right-aligns the line when it fits beside the tags,
   but the moment it wraps it is alone on its row and gets pushed to the right
   edge, which reads as a stray. Left in both cases. */
.oracle-c-needs{font-size:11.5px;color:var(--text-muted)}
.band-soon{margin-top:16px;font-size:12.5px;color:var(--text-muted);line-height:1.6}
.band-soon>span{display:inline-flex;align-items:center;gap:6px;margin-right:8px;font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text-secondary)}
.band-soon>span::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--brand-secondary)}

.app-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px}
.app-c{padding:20px;background:var(--bg-card);border:1px solid var(--border-light);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:11px}
.app-c.is-soon{background:var(--bg-card-hover)}
.app-c-top{display:flex;align-items:flex-start;gap:12px}
.app-c-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:color-mix(in srgb,var(--brand-primary) 8%,transparent);display:flex;align-items:center;justify-content:center;font-size:19px}
.app-c h3{font-size:16px;font-weight:700;line-height:1.3}
.app-c-aud{display:block;margin-top:2px;font-size:10px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;color:var(--brand-primary)}
.app-c-line{font-size:13px;color:var(--text-secondary);line-height:1.6}
.app-c-feat{list-style:none;margin:0;padding:0;font-size:12.5px;color:var(--text-secondary);line-height:1.75;flex:1 1 auto}
.app-c-feat li::before{content:'✓ ';color:var(--brand-primary);font-weight:700}
.app-c-get{display:flex;flex-wrap:wrap;align-items:center;gap:9px;margin-top:auto}
.app-c-get a{display:inline-block;line-height:0}
.app-c-get img{display:block;height:38px;width:auto}
.app-c-soon{display:inline-flex;align-items:center;gap:7px;font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted)}
.app-c-soon::before{content:'';width:7px;height:7px;border-radius:50%;background:var(--brand-secondary)}

/* A report with a published sample: the row (opens the detail) and a real
   link to the sample, side by side. They are siblings rather than nested
   because the row is a <button>, and an <a> inside a button is invalid and
   unreachable by keyboard. */
.cat-rowwrap{display:flex;align-items:stretch;border-bottom:1px solid var(--bg-code)}
.cat-rowwrap:last-child{border-bottom:0}
.cat-rowwrap>.cat-row{border-bottom:0;flex:1 1 auto;min-width:0}
.cat-sample{flex-shrink:0;display:flex;flex-direction:column;justify-content:center;gap:1px;padding:15px 20px 15px 8px;font-size:12px;font-weight:700;color:var(--brand-primary);white-space:nowrap;text-align:right}
.cat-sample:hover{background:var(--bg-card-hover);opacity:1}
.cat-sample:focus-visible{outline:2px solid var(--brand-primary);outline-offset:-2px}
.cat-sample-sub{font-size:10px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--text-muted)}

/* Beside the row is a desktop arrangement. On a phone it was catastrophic and
   silently so: .cat-sample is flex-shrink:0 and white-space:nowrap, so it takes
   ~150px and never gives any back. With the 38px monogram and the gaps, the
   row's own text column was left TWELVE PIXELS wide — every word wrapped onto
   its own line and a report row ran 320-480px instead of 69px. Nothing
   overflowed, which is why it went unnoticed: flex squeezing does not push the
   page wide, it destroys the row instead.
   Under the row below 600px, indented to the text column it belongs to. */
@media (max-width:600px){
  .cat-rowwrap{flex-wrap:wrap}
  .cat-rowwrap>.cat-row{flex:1 1 100%}
  .cat-sample{flex:1 1 100%;flex-direction:row;flex-wrap:wrap;align-items:baseline;justify-content:flex-start;gap:2px 9px;white-space:normal;text-align:left;padding:0 20px 14px 73px}
  /* The container may wrap; its two phrases may not. Lifting nowrap from the
     link as a whole let "Read a sample" and its arrow land on separate lines. */
  .cat-sample>span{white-space:nowrap}
}
