/* ============ SALES EDUCATION DESIGN SYSTEM ============
   Token layers (EPM-62):
     1  primitives: brand palette, alphas, radii, weights, motion, font. Never themed.
     B  BRIDGE: value-named type sizes and tracking, collapsed into role names in step 2 (H1).
        Do not add new usages; the audit counts them per PR.
     2  semantic roles: surfaces, text, borders, accent, focus, shadows, status, medals.
        The only layer a theme overrides: see the html[data-theme=dark] block below.
     3  component tokens.
   Theme selection happens in JS via html[data-theme] only; no prefers-color-scheme here. */
:root{
  /* 1 primitives */
  --se-black:#000000; --se-yellow:#f9cb0c; --se-slate:#2d3e50; --se-white:#ffffff;
  --se-yellow-50:#fffcee; --se-yellow-100:#fef7d8; --se-yellow-200:#fdeeab; --se-yellow-300:#e9d78a; --se-yellow-500:#dfb50a; --se-yellow-600:#c19c07;
  --ink-50:#f7f7f7; --ink-100:#efefef; --ink-200:#e2e2e2; --ink-300:#cfcfcf;
  --slate-100:#e8ecf1; --slate-900:#16202b;
  --white-a28:rgba(255,255,255,.28); --white-a40:rgba(255,255,255,.4); --white-a45:rgba(255,255,255,.45); --white-a60:rgba(255,255,255,.6); --white-a66:rgba(255,255,255,.66); --white-a72:rgba(255,255,255,.72); --white-a75:rgba(255,255,255,.75); --white-a78:rgba(255,255,255,.78); --white-a88:rgba(255,255,255,.88); --white-a90:rgba(255,255,255,.9);
  --black-a20:rgba(0,0,0,.2); --black-a35:rgba(0,0,0,.35); --black-a50:rgba(0,0,0,.5); --black-a55:rgba(0,0,0,.55); --black-a65:rgba(0,0,0,.65); --black-a72:rgba(0,0,0,.72); --black-a88:rgba(0,0,0,.88); --black-a92:rgba(0,0,0,.92);
  --radius-sm:6px; --radius-md:8px; --radius-lg:14px; --radius-pill:99px; --radius-bar:4px;
  --fw-regular:400; --fw-medium:500; --fw-bold:700; --fw-extrabold:800; --fw-black:900;
  --ease:cubic-bezier(.2,.6,.2,1);
  --font:'Roboto',-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;
  /* Display face for headings (EPM-90 redesign): Archivo variable, slightly
     extended via font-stretch. Falls back to bold Roboto until the font file
     arrives; every heading keeps working without it. */
  --font-display:'Archivo',var(--font);
  /* B BRIDGE: value-named, collapsed in step 2 (H1) */
  --fs-10:10px; --fs-10-5:10.5px; --fs-11:11px; --fs-11-5:11.5px; --fs-12:12px; --fs-12-5:12.5px; --fs-13:13px; --fs-13-5:13.5px;
  --fs-14:14px; --fs-14-5:14.5px; --fs-15:15px; --fs-16:16px; --fs-17:17px; --fs-18:18px; --fs-22:22px;
  --fs-r092:.92rem; --fs-r1:1rem; --fs-r102:1.02rem; --fs-r105:1.05rem; --fs-r110:1.1rem; --fs-r115:1.15rem; --fs-r125:1.25rem;
  --fs-r130:1.3rem; --fs-r1375:1.375rem; --fs-r150:1.5rem; --fs-r175:1.75rem;
  /* Scale flattened with the EPM-90 redesign (Sebastian: headings were far too
     loud): hero tops out at 46px instead of 54, section headings at 32. */
  --fs-h1:clamp(1.6rem,3vw,2.125rem); --fs-h1-hero:clamp(1.8rem,3.3vw,2.875rem); --fs-h1-form:clamp(1.5rem,3vw,2rem); --fs-h1-dash:clamp(1.5rem,2.8vw,1.9rem); --fs-h2:clamp(1.3rem,2.4vw,2rem);
  --ls-tighter:-.02em; --ls-tight:-.01em; --ls-01:.01em; --ls-02:.02em; --ls-03:.03em; --ls-04:.04em; --ls-05:.05em; --ls-06:.06em;
  --ls-08:.08em; --ls-10:.1em; --ls-16:.16em; --ls-18:.18em; --ls-20:.2em; --ls-22:.22em; --ls-stars:1px;
  /* 2 semantic roles (themed) */
  --surface-page:#ffffff; --surface-card:#ffffff; --surface-raised:var(--surface-card); --surface-embed:transparent;
  --surface-input:var(--se-white); --surface-hover:#f3f3f3; --surface-hover-soft:var(--ink-50); --surface-zebra:#fafafa;
  --surface-muted:var(--ink-100); --surface-track:var(--ink-200); --surface-accent-soft:var(--se-yellow-50); --surface-accent-tint:var(--se-yellow-100);
  --surface-info:var(--slate-100); --surface-inverse:var(--se-black); --surface-backdrop:var(--black-a55);
  /* Warm ground for the community band (EPM-90): white tinted toward the brand
     yellow, with a matching hairline. */
  --surface-community:#f8f5ee; --border-community:#e3ded1;
  --text-heading:#000000; --text-body:#1c1c1c; --text-muted:#6b6b6b; --text-strong:var(--se-black);
  /* The select field's arrow as an image, because Chrome ignores the right
     padding for the native one: measured, it stays 4.7px from the edge no
     matter whether padding-right is 10, 22 or 30px (9 Sep, Sebastian: "kein
     padding zum rechten rand"). The colour therefore lives here and not in the
     rule, and it is the same as --text-body so the arrow follows the theme. */
  --select-arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%231c1c1c' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --text-on-accent:var(--se-black); --text-inverse:var(--se-white); --text-inverse-soft:var(--white-a88); --text-code:#f2efe2;
  --accent:var(--se-yellow); --accent-hover:var(--se-yellow-500); --accent-press:var(--se-yellow-600); --accent-edge:var(--se-yellow-600);
  --accent-text:#8a6d00; --info-accent:var(--se-slate);
  --border-subtle:#e4e4e4; --border-input:var(--ink-300); --border-strong:var(--se-black); --border-focus:var(--se-yellow);
  --border-accent-soft:var(--se-yellow-300); --border-accent-tint:var(--se-yellow-200); --border-info:#d3dbe4; --border-inverse-soft:var(--white-a28);
  --focus-ring:0 0 0 3px rgba(249,203,12,.3);
  /* The pinned button bar in a widget, lifted off the rows that scroll
     beneath it. Tight like an app bar's elevation, not a long gradient. */
  /* Edge of the sticky bar, used on the narrow layout only. Set on 4 Sep as a
     replacement for a soft, far-reaching shadow, dialled back once more on
     9 Sep: 18px of reach and edge 214 read as a plume rather than an edge
     (Sebastian: "ein bisschen zu stark"). Now 10px and edge 233, measured
     against white with the bar in place. Both changes together were needed:
     only making it lighter left the plume standing, only making it tighter
     left it dark. On the wide layout a divider line applies instead, see the
     comment at the rule. */
  --shadow-sticky-edge:0 -4px 10px -3px rgba(0,0,0,.16);
  --shadow-md:0 2px 6px rgba(0,0,0,.08), 0 8px 24px rgba(0,0,0,.07);
  --shadow-modal:0 24px 64px var(--black-a35);
  --shadow-accent:0 4px 18px rgba(249,203,12,.45);
  --heading-shadow-accent:1px 2px 0 var(--black-a50); --heading-shadow-accent-strong:1px 2px 0 var(--black-a65);
  --status-success-text:#2e9e5b; --status-success-fill:#2e9e5b; --status-danger-text:#d64545; --status-danger-text-strong:#B0402A; --status-danger-border:#d64545;
  --status-success-soft-bg:#e7f3ec; --status-success-soft-text:#1f6b3e; --status-success-soft-border:#bfdccb;
  --medal-gold-bg:var(--accent); --medal-gold-text:var(--se-black); --medal-gold-edge:var(--accent-edge);
  --medal-silver-bg:#d4d9df; --medal-silver-text:#2b2f36; --medal-silver-edge:#9aa3ad;
  --medal-bronze-bg:#d8b08a; --medal-bronze-text:#3a2614; --medal-bronze-edge:#a5744a;
  --badge-bronze:#7e5433; --badge-bronze-deep:#63421f; --badge-silver:#5f6a77; --badge-silver-deep:#4c545f;
  --badge-gold:#8a691f; --badge-gold-deep:#6f5419; --badge-platinum:#6E7F96; --badge-platinum-deep:#4C5B70;
  /* 3 component tokens */
  --strip-pad-y:11px; --strip-pad-x:16px;
  /* Floor for anything the user types into: below 16px iOS Safari zooms on
     focus, and inside Mighty's iframe that shifts the whole host page. A
     component token, not a BRIDGE size, because the number is a constraint
     of the platform rather than a step on the type scale. */
  --field-text:16px; --filter-text:13.5px;
  /* The validation message in the pinned footer sits next to buttons set at
     14px in black weight, so at the form's 13px it read as a footnote
     (Sebastian, 4 Sep). One step up, and bold, to match their weight. */
  --footer-err-text:15px; --footer-err-text-wide:18px;
}

/* Dark theme (EPM-62 scaffold, completed in EPM-75 on 9 Sep 2026). Only
   semantic roles flip; primitives are never themed. Neutrals come from one
   ramp so the hue can be retuned in one place after the Mighty measurement
   (docs/design-system.md) - the ramp values are still provisional until then.
   Every semantic role now carries a deliberate dark value. Roles that keep
   their light value are brand constants (the yellow accent family, the black
   inverse surfaces, medal and badge chips): they are set explicitly anyway so
   the missing-role count stays zero and the choice is visible - do not remove
   them as redundant. Every page follows the device by default since EPM-75,
   the theme parameter overrides (head script in index.html). */
html[data-theme=dark]{
  color-scheme:dark;
  /* Ramp matched to Mighty's measured dark UI on 10 Sep 2026 (Sebastian:
     the widgets shall blend in completely). Mighty is exactly neutral grey,
     content #171717, so the ramp is neutral with dark-0 on that value; the
     steps keep their old lift. The accent stays FULL #f9cb0c on purpose,
     although Mighty dims its own to #c6a10b: their dim sits in the chrome,
     ours sits on the actions. */
  --dark-0:#171717; --dark-1:#1b1b1b; --dark-2:#1f1f1f; --dark-3:#232323; --dark-4:#292929; --dark-5:#2f2f2f;
  --surface-page:var(--dark-0); --surface-card:var(--dark-2); --surface-raised:var(--dark-4); --surface-embed:transparent;
  --surface-input:var(--dark-1); --surface-hover:var(--dark-4); --surface-hover-soft:var(--dark-3); --surface-zebra:var(--dark-3);
  --surface-muted:var(--dark-5); --surface-track:var(--dark-5); --surface-accent-soft:rgba(249,203,12,.10); --surface-accent-tint:rgba(249,203,12,.16);
  --surface-info:#1e2530; --surface-backdrop:rgba(0,0,0,.7);
  --surface-community:var(--dark-2); --border-community:var(--dark-5);
  --text-heading:#f5f5f5; --text-body:#e6e6e6; --text-muted:#a9a9a9; --text-strong:#ffffff;
  --select-arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23e6e6e6' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --accent-text:var(--se-yellow); --info-accent:#a9bdd3;
  --border-subtle:#2e2e2e; --border-input:#626262; --border-strong:#e6e6e6;
  --border-accent-soft:rgba(249,203,12,.35); --border-accent-tint:rgba(249,203,12,.3); --border-info:#2f3a48;
  --focus-ring:0 0 0 3px rgba(249,203,12,.55);
  --shadow-sticky-edge:0 -4px 10px -3px rgba(0,0,0,.4);
  --shadow-md:0 0 0 1px rgba(255,255,255,.04), 0 8px 24px rgba(0,0,0,.5);
  --shadow-modal:0 0 0 1px rgba(255,255,255,.06), 0 24px 64px rgba(0,0,0,.6);
  --status-success-text:#4cc27a; --status-success-fill:#4cc27a; --status-danger-text:#f06a6a; --status-danger-text-strong:#f08a7a; --status-danger-border:#f06a6a;
  --status-success-soft-bg:#173523; --status-success-soft-text:#8fd9a8; --status-success-soft-border:#2b5a3c;
  /* Brand constants, same value as light on purpose (EPM-75). The yellow
     family reads on a dark ground even better than on white, and black on
     yellow stays the button/medal text in both themes. */
  --accent:var(--se-yellow); --accent-hover:var(--se-yellow-500); --accent-press:var(--se-yellow-600); --accent-edge:var(--se-yellow-600);
  --text-on-accent:var(--se-black); --border-focus:var(--se-yellow);
  --shadow-accent:0 4px 18px rgba(249,203,12,.45);
  --heading-shadow-accent:1px 2px 0 var(--black-a50); --heading-shadow-accent-strong:1px 2px 0 var(--black-a65);
  /* Inverse surfaces stay pure black: still the darkest plane next to the
     --dark-* ramp, and the separation comes from the yellow edge, as in
     light (embed bar, active sub-tab; header/footer/hero exist only on the
     standalone page, which never gets this theme). */
  --surface-inverse:var(--se-black);
  --text-inverse:var(--se-white); --text-inverse-soft:var(--white-a88); --border-inverse-soft:var(--white-a28);
  --text-code:#f2efe2;
  /* Medal chips stay bright in both themes: rank medals are meant to pop on
     the board, and gold is the brand yellow either way. */
  --medal-gold-bg:var(--accent); --medal-gold-text:var(--se-black); --medal-gold-edge:var(--accent-edge);
  --medal-silver-bg:#d4d9df; --medal-silver-text:#2b2f36; --medal-silver-edge:#9aa3ad;
  --medal-bronze-bg:#d8b08a; --medal-bronze-text:#3a2614; --medal-bronze-edge:#a5744a;
  /* Badge fills unchanged: the mid-tone metals hold on both grounds. Their
     known AA shortfall (white text on gold/silver, step-2 item 27) applies to
     both themes equally and is decided there, not here. */
  --badge-bronze:#7e5433; --badge-bronze-deep:#63421f; --badge-silver:#5f6a77; --badge-silver-deep:#4c545f;
  --badge-gold:#8a691f; --badge-gold-deep:#6f5419; --badge-platinum:#6E7F96; --badge-platinum-deep:#4C5B70;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;overscroll-behavior-y:none}
body{background:var(--surface-page);color:var(--text-body);font-family:var(--font);font-size:var(--fs-16);line-height:1.6}
/* Headings in mixed case since the EPM-90 redesign: the shouting all-caps
   display was the number-one client complaint. Weight stays at bold; the
   presence comes from the slightly extended Archivo, not from size or caps. */
h1,h2,h3,h4{font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);line-height:1.15;color:var(--text-heading);letter-spacing:var(--ls-tight)}
h1{font-size:var(--fs-h1)}
h2{font-size:var(--fs-h2)}
h3{font-size:var(--fs-r125)}
p{color:var(--text-body)}
a{color:var(--accent-text);font-weight:var(--fw-medium)}
/* iOS Safari paints button text in its link blue unless a colour is set. */
button{font-family:var(--font);color:inherit}
.ico{width:1.2em;height:1.2em;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round;vertical-align:-.22em;display:inline-block}
/* Small uppercase label role. Size, tracking and colour differ per member today
   (step 2 decision H2); the shared block carries only what they agree on. */
.label-caps,.kicker,.eyebrow,.tile .t-label,.filterbar label,.board-table th,.sum-table th,.badge-card .dur,.brand-name small{text-transform:uppercase;font-weight:var(--fw-bold)}

/* ---------- Header / Tabs ---------- */
/* Sticky again (EPM-90, second round): position:fixed turned out worse on
   iOS - with the keyboard open it behaves as absolute and the bar scrolls
   away under the form. Sticky has neither problem; the PWA rubber-band that
   motivated fixed is tamed at the root instead (overscroll-behavior on html). */
.site-header{position:sticky;top:0;z-index:60;background:var(--surface-inverse);border-bottom:3px solid var(--accent)}
.header-inner{max-width:1240px;margin:0 auto;padding:12px 24px;display:flex;align-items:center;gap:24px;flex-wrap:nowrap}
.brand{display:flex;align-items:center;gap:12px}
/* The Sales Education mark (EPM-78): the white/yellow puzzle head from Marc's
   own brand, the same one on his hoodie in the hero photo. Derived from the
   site's 512px logo; swap in the vector once his designer provides it. */
.brand-mark{width:42px;height:42px;display:block}
.brand-name{color:var(--text-inverse);font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);font-size:var(--fs-17);line-height:1.15}
.brand-name small{display:block;font-size:var(--fs-10-5);letter-spacing:var(--ls-22);color:var(--accent)}
/* Navigation as quiet text links since EPM-90; the active page carries the
   yellow underline, the submit action is the one filled button. Below 900px
   the row gives way to the burger menu. */
.main-tabs{display:flex;gap:32px;margin-left:auto;align-items:center}
.main-tab{border:none;background:transparent;color:var(--white-a72);padding:8px 0;font-size:14px;font-weight:var(--fw-medium);cursor:pointer;transition:.2s var(--ease);border-bottom:2px solid transparent}
.main-tab:hover{color:var(--text-inverse)}
.main-tab.active{color:var(--text-inverse);font-weight:var(--fw-bold);border-bottom-color:var(--accent)}
/* Outline instead of a filled block (Sebastian, 11 Sep: too prominent next
   to the text links). The fill answers hover and the active page. */
.main-tab.cta{background:transparent;border:1px solid var(--accent);color:var(--accent);font-weight:var(--fw-bold);padding:11px 22px;border-radius:var(--radius-md)}
.main-tab.cta:hover,.main-tab.cta.active{background:var(--accent);border-color:var(--accent);color:var(--text-on-accent)}
/* Burger button: hidden on desktop, the only nav control on phones. 44px hit
   target; the icon swaps to a cross while the menu is open. */
.burger{display:none;background:none;border:none;cursor:pointer;width:44px;height:44px;align-items:center;justify-content:center;color:var(--text-inverse);margin-left:auto}
.burger .ico-close{display:none}
html.menu-open .burger .ico-lines{display:none}
html.menu-open .burger .ico-close{display:block}
/* Full-screen menu panel under the sticky header (z below it so the burger
   stays reachable as the close control). */
.mobile-menu{display:none;position:fixed;inset:0;z-index:55;background:var(--se-black);padding:96px 32px 28px;flex-direction:column}
html.menu-open .mobile-menu{display:flex}
html.menu-open{overflow:hidden}
.mobile-menu nav{flex:1;display:flex;flex-direction:column;justify-content:center;gap:30px;align-items:flex-start}
.mobile-menu .main-tab{font-family:var(--font-display);font-stretch:105%;font-size:24px;font-weight:var(--fw-bold);color:var(--white-a78);padding:0 0 8px;border-bottom:3px solid transparent}
.mobile-menu .main-tab.active{color:var(--text-inverse);border-bottom-color:var(--accent)}
.mobile-menu .menu-foot{color:var(--white-a45);font-size:12px;text-align:center;margin-top:18px}

.page{display:none}
.page.active{display:block}
.wrap{max-width:1240px;margin:0 auto;padding:0 24px}
.page-pad{max-width:1240px;margin:0 auto;padding:34px 24px 90px}

/* ---------- Hero (EPM-90 redesign): Marc's photo as a cleanly cropped block
   inside the content column, text beside it on solid black - never over the
   photo (Sebastian, 11 Sep). The band itself stays full-bleed black; only the
   photo is boxed to the 1240px grid. Below 900px the photo stacks on top and
   the copy follows on the black ground. ---------- */
.hero-dark{background:linear-gradient(150deg,var(--se-black) 0%,var(--se-black) 45%,var(--slate-900) 100%);color:var(--text-inverse);position:relative;overflow:hidden}
.hero-inner{max-width:1240px;margin:0 auto;padding:64px 24px 40px;position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:64px;align-items:center}
.hero-photo{position:relative;min-height:500px;border-radius:var(--radius-lg);overflow:hidden}
.hero-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:22% 20%;filter:brightness(.9) saturate(.9)}
/* One quiet scrim grounding the photo's lower edge; no text ever sits on it. */
.hero-photo::before{content:'';position:absolute;inset:0;background:linear-gradient(0deg,var(--black-a35) 0%,transparent 45%)}
.hero-inner .content{max-width:600px}
.hero-dark h1{color:var(--text-inverse);font-size:var(--fs-h1-hero)}
.hero-rule{width:72px;height:4px;background:var(--accent);margin:26px 0 22px}
.hero-dark p.lead{font-size:var(--fs-r115);color:var(--text-inverse-soft);max-width:560px}
.hero-dark p.lead strong{color:var(--text-inverse)}
.hero-facts{display:flex;gap:48px;margin-top:40px;border-top:1px solid var(--white-a28);padding-top:22px;flex-wrap:wrap}
.hero-facts .num{font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);font-size:22px;color:var(--accent);display:block;font-variant-numeric:tabular-nums}
.hero-facts small{font-size:13px;color:var(--white-a66);display:block;margin-top:4px}
.slant{display:block;width:100%;height:56px;margin-top:-1px;position:relative;z-index:2}
/* The two page-coloured wedges of the slant follow the page surface, so a dark
   theme does not leave a white wedge under the hero. */
.slant .to-page{fill:var(--surface-page)}
/* Plain letterspaced kicker since EPM-90 (the yellow pill stacked a third
   yellow signal into the hero). Muted on dark ground, small caps stay. */
.eyebrow{display:inline-block;font-size:12px;letter-spacing:var(--ls-18);color:var(--white-a60);margin-bottom:20px;font-weight:var(--fw-bold)}
.hero-cta{margin-top:30px;display:flex;gap:12px;flex-wrap:wrap}
@media (max-width:900px){
  .hero-inner{grid-template-columns:1fr;gap:26px;padding:24px 24px 56px}
  /* Both actions side by side (Sebastian, 13 Sep): equal halves, tighter
     padding and one type step down so the longer label fits at 390px. */
  .hero-cta{flex-wrap:nowrap;gap:10px}
  .hero-cta .btn{flex:1 1 0;justify-content:center;padding:13px 8px;font-size:13.5px;white-space:nowrap}
  .hero-photo{min-height:0;height:300px}
  .hero-photo img{object-position:26% 12%}
  .hero-inner .content{max-width:none}
  .hero-facts{gap:28px;margin-top:30px}
}

/* 13px vertical padding puts the rendered button at 44px (with the 1px
   border and the 14px black-weight line) - the thumb target of Apple's HIG
   and WCAG 2.5.5. It was 12px/42px until EPM-77 (10 Sep 2026, Sebastian's
   call after a side-by-side): the whole cost is 4px on the longest form
   step. A platform constraint like --field-text, not a type-scale step. */
/* Sentence case and bold instead of black caps since EPM-90: quieter buttons
   are part of the premium read; the yellow fill still carries the hierarchy. */
.btn{display:inline-flex;align-items:center;gap:9px;border-radius:var(--radius-md);padding:13px 24px;font-size:15px;font-weight:var(--fw-bold);cursor:pointer;border:1px solid var(--border-input);background:var(--surface-card);color:var(--text-strong);transition:.2s var(--ease);text-decoration:none}
.btn:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}
.btn:hover{border-color:var(--border-strong);background:var(--surface-hover-soft)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--text-on-accent)}
.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover);box-shadow:var(--shadow-accent);transform:translateY(-1px)}
.btn.primary:active{background:var(--accent-press);transform:none}
.btn.on-dark{background:transparent;border-color:var(--white-a40);color:var(--text-inverse)}
.btn.on-dark:hover{border-color:var(--accent);color:var(--accent);background:transparent}
.btn.small{padding:8px 14px;font-size:var(--fs-12)}
.btn.ghost{background:transparent}

.section{margin-top:72px}
.section-head{max-width:780px;margin-bottom:48px}
.section-head p{margin-top:20px;color:var(--text-muted)}
.kicker{font-size:var(--fs-11-5);letter-spacing:var(--ls-18);color:var(--accent-text);font-weight:var(--fw-black);margin-bottom:10px}
/* Signature rule under every section heading (EPM-90 polish, 11 Sep): the
   same 44px yellow line the hero and the widgets carry, so the quiet white
   sections stop floating. Scoped to .section-head: band headings and widget
   cards keep their own anatomy. */
.section-head h2::after{content:'';display:block;width:44px;height:3px;background:var(--accent);margin-top:16px}

/* Surface recipe shared by every card-like container. Padding, layout and margins
   stay with the component; .modal is not a surface (no border, own shadow). */
.surface,.card,.tile,.board,.form-card{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);box-shadow:var(--shadow-md)}
.grid{display:grid;gap:18px}
.grid.c2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.grid.c3{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.pad{padding:26px}
.card h3{margin-bottom:8px;font-size:var(--fs-r105)}
.card p{font-size:var(--fs-15)}
ul.clean{list-style:none;margin-top:12px}
ul.clean li{font-size:var(--fs-14-5);color:var(--text-body);padding:5px 0 5px 28px;position:relative}
/* Yellow dash instead of the triangle since EPM-90: the arrowheads read as
   template decoration, the short rule reads as the brand's slant. */
ul.clean li::before{content:"";position:absolute;left:2px;top:15px;width:16px;height:2px;background:var(--accent)}

/* ---------- Landing sections (EPM-90): columns on hairline rules instead of
   boxed cards. The first column carries the yellow rule, the rest stay grey. */
.rail-grid{display:grid;gap:44px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.rail{border-top:2px solid var(--border-subtle);padding-top:26px}
.rail.key{border-top-color:var(--accent)}
.rail-head{display:flex;align-items:center;gap:12px;margin-bottom:10px}
.rail-head .ico{width:24px;height:24px;color:var(--text-strong)}
.rail h3{font-size:20px}
.rail h3 .no{color:var(--accent-text);font-variant-numeric:tabular-nums}
.rail p{font-size:15px;color:var(--text-muted);line-height:1.65;margin-top:10px}
/* Warm tinted full-bleed band between hero and points band (EPM-90 polish):
   the all-white stretch read as unfinished; the tint gives the page the
   white / warm / black rhythm of the approved canvas. */
.tint-band{background:var(--surface-community);margin-top:70px}
.tint-band .band-pad{max-width:1240px;margin:0 auto;padding:64px 24px 72px}
.tint-band .section{margin-top:0}
.tint-band .rail{border-top-color:var(--border-community)}
.tint-band .rail.key{border-top-color:var(--accent)}
.tint-band+.points-band{margin-top:0}
.tint-band+.points-band .band-slant.top .to-page{fill:var(--surface-community)}

/* Full-bleed black band with the points calculation as the centrepiece. */
.points-band{position:relative;background:var(--surface-inverse);color:var(--text-inverse);padding:100px 0 110px;margin-top:70px}
.band-slant{position:absolute;left:0;right:0;width:100%;height:52px;display:block}
.band-slant.top{top:-1px}
.band-slant.bottom{bottom:-1px}
.band-slant .to-page{fill:var(--surface-page)}
.points-band .band-inner{max-width:1240px;margin:0 auto;padding:0 24px;display:grid;grid-template-columns:7fr 5fr;gap:72px;align-items:center}
.points-band h2{color:var(--text-inverse)}
.points-band .band-sub{color:var(--white-a75);margin:14px 0 38px;max-width:520px}
.calc-line{font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);font-size:clamp(1.6rem,3.2vw,2.875rem);line-height:1.2;font-variant-numeric:tabular-nums;color:var(--text-inverse)}
.calc-line .hl{color:var(--accent)}
.point-list{border-left:1px solid var(--border-inverse-soft);padding-left:44px;display:flex;flex-direction:column;gap:18px}
.point-list .row{display:flex;gap:18px;align-items:baseline}
.point-list .val{font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);font-size:19px;color:var(--accent);min-width:96px;font-variant-numeric:tabular-nums}
.point-list .lbl{color:var(--text-inverse-soft);font-size:15px}
@media (max-width:900px){
  .points-band{padding:72px 0 84px}
  .points-band .band-inner{grid-template-columns:1fr;gap:32px}
  .point-list{border-left:none;padding-left:0;border-top:1px solid var(--border-inverse-soft);padding-top:22px}
  .calc-line{text-align:center}
}

/* Community: the warm ground runs full-bleed, the photo sits boxed inside the
   1240px content grid (Sebastian, 11 Sep: photos in the content column, not
   edge to edge). */
.community-band{background:var(--surface-community);margin-top:70px}
.community-band .band-pad{max-width:1240px;margin:0 auto;padding:64px 24px;display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
.community-band .photo{position:relative;min-height:400px;border-radius:var(--radius-lg);overflow:hidden}
.community-band .photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 30%;display:block}
.community-band .text p{margin-top:14px;line-height:1.75}
.founder{display:flex;align-items:center;gap:14px;border-top:1px solid var(--border-community);padding-top:20px;margin-top:26px}
.founder img{width:44px;height:44px;border-radius:50%;object-fit:cover;object-position:24% 18%}
.founder b{display:block;font-size:15px;color:var(--text-strong)}
.founder small{color:var(--text-muted);font-size:13px}
@media (max-width:900px){
  .community-band{margin-top:56px}
  .community-band .band-pad{grid-template-columns:1fr;gap:26px;padding:32px 24px 44px}
  .community-band .photo{min-height:0;height:240px}
}

/* Closing: one action over the darkened team photo. */
.closing-band{position:relative;background:var(--surface-inverse);color:var(--text-inverse);text-align:center;overflow:hidden;margin-top:70px}
.closing-band .backdrop{position:absolute;inset:0}
.closing-band .backdrop img{width:100%;height:100%;object-fit:cover;object-position:50% 28%;filter:brightness(.5) saturate(.7)}
.closing-band .backdrop::after{content:'';position:absolute;inset:0;background:linear-gradient(0deg,var(--black-a92) 0%,var(--black-a72) 55%,var(--black-a88) 100%)}
.closing-band .band-inner{position:relative;z-index:2;max-width:1240px;margin:0 auto;padding:104px 24px 78px}
.closing-band h2{color:var(--text-inverse);font-size:clamp(1.5rem,2.6vw,2.375rem)}
.closing-band h2 .hl{color:var(--accent)}
.closing-band .band-inner>p{color:var(--white-a78);max-width:560px;margin:18px auto 34px;line-height:1.7}
@media (max-width:900px){.closing-band .band-inner{padding:80px 24px 56px}}


/* Editorial numbered rows since EPM-90 (five identical shadow cards were the
   textbook AI-kit pattern): a real sequence on hairlines, the number set in
   the display face like the three-step rail above. */
.steps{display:grid;gap:0;margin-top:8px;border-top:2px solid var(--accent)}
.step{display:flex;gap:22px;padding:22px 0;align-items:flex-start;border-bottom:1px solid var(--border-subtle);background:transparent}
.step:last-child{border-bottom:none}
.step-no{flex:0 0 auto;min-width:34px;font-family:var(--font-display);font-stretch:105%;font-weight:var(--fw-bold);font-size:20px;color:var(--accent-text);font-variant-numeric:tabular-nums;line-height:1.3}
.step h3{font-size:17px;margin-bottom:4px}
.step p{font-size:var(--fs-14-5);color:var(--text-muted)}

/* Uniform hairline, no accent bar on the left (decision of 3 Sep 2026): the
   tint already tells the box kinds apart, and the bar read as a template. */
.callout,.note,.info-callout{border:1px solid;border-radius:var(--radius-md);color:var(--text-body)}
.note{background:var(--surface-accent-tint);border-color:var(--border-accent-tint);padding:14px 18px;font-size:var(--fs-14);margin-top:16px}
.note strong{color:var(--text-strong)}
/* On the landing page the repeated yellow alert boxes read as template
   scaffolding (EPM-90 research pass): asides become quiet text over a soft
   yellow rule. Widgets keep the box, there it is functional UI. */
#page-welcome .note{background:transparent;border:none;border-top:1px solid var(--border-accent-soft);border-radius:0;padding:16px 0 0;color:var(--text-muted)}

.badge-row{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));margin-top:6px}
.badge-card{border-radius:var(--radius-lg);padding:22px;color:var(--text-inverse);position:relative;overflow:hidden;box-shadow:var(--shadow-md)}
.badge-card h3{color:var(--text-inverse);font-size:var(--fs-r1)}
.badge-card .dur{font-size:var(--fs-11);letter-spacing:var(--ls-16);opacity:.9;margin-bottom:8px;display:block}
/* Full white since EPM-90: the metal fills were darkened to pass AA (4.5:1)
   for every text on them, and the 90% white gave that margin away again. */
.badge-card p{color:var(--text-inverse);font-size:var(--fs-13-5);margin-top:6px}
/* Flat medal ladder since EPM-90 (gradients read as 2015 SaaS): bronze, silver
   and gold reuse the rank-medal vocabulary, and the top tier is the brand
   itself - black with the yellow duration, edged so it holds on dark ground. */
.badge-card.bronze{background:var(--badge-bronze)}
.badge-card.silber{background:var(--badge-silver)}
.badge-card.gold{background:var(--badge-gold)}
.badge-card.platin{background:var(--surface-inverse);border:1px solid var(--accent-edge)}
.badge-card.platin .dur{color:var(--accent);opacity:1}

/* ---------- Dashboard ---------- */
.dash-top{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;flex-wrap:wrap;margin-bottom:20px}
/* Underline tabs since EPM-90 (Sebastian's pick over pills, select and a
   segmented bar): the header nav's own language. One row that scrolls
   sideways on phones - the fade edge below hints at more. */
/* touch-action:pan-x pins the row to its one axis: in the installed PWA iOS
   otherwise accepts diagonal pans and rubber-bands the whole bar (Sebastian,
   11 Sep: "schwimmt"). Vertical swipes fall through to the page. */
.sub-nav{display:flex;gap:28px;margin-bottom:24px;border-bottom:1px solid var(--border-subtle);overflow-x:auto;overflow-y:hidden;touch-action:pan-x;overscroll-behavior-x:contain;scrollbar-width:none;scroll-snap-type:x proximity}
.sub-nav::-webkit-scrollbar{display:none}
.sub-tab{border:none;background:transparent;padding:10px 2px 12px;font-size:15px;font-weight:var(--fw-medium);color:var(--text-muted);cursor:pointer;border-bottom:3px solid transparent;margin-bottom:-1px;flex:0 0 auto;scroll-snap-align:start;white-space:nowrap;transition:.2s var(--ease)}
.sub-tab:hover{color:var(--text-strong)}
.sub-tab.active{color:var(--text-strong);font-weight:var(--fw-bold);border-bottom-color:var(--accent)}
@media (max-width:720px){
  .sub-nav{padding-right:36px;mask-image:linear-gradient(90deg,rgb(0,0,0) calc(100% - 36px),transparent);-webkit-mask-image:linear-gradient(90deg,rgb(0,0,0) calc(100% - 36px),transparent)}
}

/* Flat since EPM-90: the boxed filter card was one more block of chrome on an
   already crowded screen; the fields carry their own edges. */
.filterbar{display:flex;gap:14px;flex-wrap:wrap;align-items:flex-end;margin-bottom:22px}
/* In embeds the widget body is transparent (the host shows through), so the
   flat bar would float its dark-theme labels on an unknown ground: there the
   filter row keeps its own surface, like every other widget block. */
html.embed .filterbar{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);padding:14px 16px;gap:10px}
/* Two fields share one row even in Mighty's narrow column (Sebastian, 13 Sep:
   the stacked fields were a redesign regression): each group takes half the
   row, a third field wraps as a pair. */
html.embed .filterbar .f-group{flex:1 1 45%;min-width:0}
.filterbar label{font-size:var(--fs-11);color:var(--text-muted);display:block;margin-bottom:3px;letter-spacing:var(--ls-08)}
.f-group{min-width:130px}
.filterbar .f-search{min-width:190px}
/* 16px is not cosmetic: below it iOS Safari zooms into the page when a field is
   focused, and inside Mighty's iframe that shifts the whole host page. With
   11px padding the field also clears the 44px touch target (was 34px). The
   filter bars keep their compact size through their own rule below. */
select,input[type=text],input[type=email],input[type=date],input[type=number]{
  font-family:var(--font);font-size:var(--field-text);color:var(--text-body);
  background:var(--surface-input);border:1px solid var(--border-input);border-radius:var(--radius-md);
  padding:11px 12px;outline:none;width:100%;transition:border .2s,box-shadow .2s}
/* Our own arrow instead of the native one. Reason and measurement live at the
   --select-arrow token. The distance to the right edge is thereby fixed and
   equals the text inset on the left; with the native arrow it was set by the
   browser and no amount of padding could move it. Applies to EVERY select, not
   just the filter bar: two kinds of arrow side by side would be worse than the
   original problem. The right padding carries text inset plus arrow width plus
   air, so a long entry does not run underneath it. */
select{appearance:none;-webkit-appearance:none;
  background-image:var(--select-arrow);background-repeat:no-repeat;
  background-position:right 12px center;background-size:10px 6px;
  padding-right:30px}
select:focus,input:focus{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
/* iOS Safari gives date inputs an intrinsic width and ignores width:100%, which
   pushed the field out of the card on phones. */
input[type=date]{min-width:0;max-width:100%;display:block;-webkit-appearance:none;appearance:none}
/* The native number spinner appears on hover/focus (WebKit) and pushes the
   centred count out of the middle of the field (EPM-77, Sebastian 10 Sep
   2026). Counts are typed - inputmode=numeric keeps the number pad on
   phones - so the spinner goes. Firefox needs the textfield appearance. */
input[type=number]{-moz-appearance:textfield;appearance:textfield}
input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
.filterbar .spacer{flex:1}
/* Filter controls sit on the table's type size, 13.5px (EPM-61, 29 Aug). On
   desktop that continues to apply unchanged, for both kinds of field.
   On 4 Sep I had raised the search field to 16px against the iOS zoom and left
   the select alone, reasoning that a select opens a picker and never zooms. I
   never verified that claim, and by everything documented about iOS Safari it
   is at least doubtful. The result was two differently sized fields in one
   row. Sebastian's decision of 9 Sep: 16px only where the user types. The
   zoom is a touch-device behaviour, a desktop browser does not zoom on focus.
   That leaves EPM-61 untouched on desktop, and iOS gets its 16px without
   anyone having to walk back a decision. */
.filterbar select,.filterbar input{font-size:var(--filter-text);padding:7px 10px}
/* Same spacing on the right as on the left, so 10px here instead of the form
   fields' 12px, and the padding correspondingly tighter. */
.filterbar select{background-position:right 10px center;padding-right:26px}
/* Two axes, not one. A pure width rule misses an iPad in landscape; the
   pointer query catches every touch device regardless of width. Both halves
   are tested: ux-audit.js has a state at 1024px with touch for this, because
   Playwright can indeed force pointer:coarse via isMobile. I had claimed the
   opposite before trying it. */
@media (max-width:720px), (hover:none) and (pointer:coarse){
  .filterbar select,.filterbar input{font-size:var(--field-text)}
}
.linkish{position:relative;background:none;border:none;color:var(--accent-text);font-size:var(--fs-13);font-weight:var(--fw-bold);cursor:pointer;text-decoration:underline;text-underline-offset:3px}
/* Hit area, not box. Both link-style buttons measure 15px tall, WCAG 2.5.8
   demands 24. Padding would grow the line and the focus ring along with it; a
   pseudo-element enlarges only what a finger can hit: not a pixel changes, the
   target becomes 44px tall. Same device on the dialog's close cross, which at
   12x25px was the smallest target in the application. */
.linkish::after{content:'';position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);height:44px}
.modal .close-x::after{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:44px;height:44px}

/* Channel and cluster rows as underline tabs since EPM-90, one step smaller
   than the board tabs so the two levels stay readable. Same scroll mechanics:
   one axis, hidden scrollbar, snap. Hidden in embeds as before. */
.pills{display:flex;gap:24px;margin-bottom:16px;border-bottom:1px solid var(--border-subtle);overflow-x:auto;overflow-y:hidden;touch-action:pan-x;overscroll-behavior-x:contain;scrollbar-width:none;scroll-snap-type:x proximity}
.pills::-webkit-scrollbar{display:none}
.pill{border:none;background:transparent;padding:8px 2px 10px;font-size:14px;font-weight:var(--fw-medium);color:var(--text-muted);cursor:pointer;border-bottom:3px solid transparent;margin-bottom:-1px;flex:0 0 auto;scroll-snap-align:start;white-space:nowrap;transition:.2s var(--ease)}
.pill:hover{color:var(--text-strong)}
.pill.active{color:var(--text-strong);font-weight:var(--fw-bold);border-bottom-color:var(--accent)}
/* The drill-down row's way back: reads as a link, never as a sibling tab. */
.pill-back{color:var(--accent-text);font-weight:var(--fw-bold)}
.pill-back:hover{color:var(--accent-text)}
@media (max-width:720px){
  .pills{padding-right:36px;mask-image:linear-gradient(90deg,rgb(0,0,0) calc(100% - 36px),transparent);-webkit-mask-image:linear-gradient(90deg,rgb(0,0,0) calc(100% - 36px),transparent)}
}

.tiles{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin-bottom:20px}
.tile{padding:18px 20px;text-align:center}
.tile .t-label{font-size:var(--fs-11);letter-spacing:var(--ls-10);color:var(--text-muted)}
.tile .t-value{font-weight:var(--fw-bold);font-size:var(--fs-r175);margin-top:4px;color:var(--text-strong)}
.tile .t-sub{font-size:var(--fs-12-5);color:var(--text-muted);margin-top:2px}

.board{margin-bottom:26px;overflow:hidden}
.board-head{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:18px 20px;border-bottom:1px solid var(--border-subtle)}
.board-head h3{font-size:var(--fs-r102)}
.board-head .desc{font-size:var(--fs-13);color:var(--text-muted);flex-basis:100%;margin-top:2px}
.board-head .actions{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}
.table-wrap{overflow-x:auto;max-width:100%}
table.board-table{border-collapse:separate;border-spacing:0;width:100%;font-size:var(--fs-13-5);min-width:640px}
.board-table th{font-size:var(--fs-11);letter-spacing:var(--ls-06);color:var(--text-strong);text-align:center;padding:10px 12px;border-bottom:1px solid var(--border-strong);white-space:nowrap;background:var(--surface-card)}
.board-table th.group-h{text-align:center;border-left:1px solid var(--border-subtle);color:var(--text-strong);background:var(--surface-accent-tint);border-bottom:1px solid var(--accent)}
.board-table th:first-child,.board-table td:first-child{text-align:center;width:52px}
.board-table th.txt,.board-table td.txt{text-align:left}
.board-table td{padding:9px 12px;border-bottom:1px solid var(--border-subtle);text-align:center;white-space:nowrap;color:var(--text-body)}
.board-table tbody tr:last-child td{border-bottom:none}
.board-table tbody tr:hover td{background:var(--surface-hover)}
.board-table td.rank{font-weight:var(--fw-bold);color:var(--text-strong)}
.board-table .nick{color:var(--text-strong);font-weight:var(--fw-medium);cursor:pointer;text-decoration:underline;text-decoration-color:transparent;transition:.2s}
.board-table .nick:hover{text-decoration-color:var(--accent);text-decoration-thickness:2px}
/* The name opens the participant's profile. The handler sits on the cell, not
   on the text: as inline text the target was 40x16, a third of the cell, and
   styling the text as a block re-laid out the glyphs. This way the target is
   the full cell and not one pixel moves. */
.board-table td.nick-cell{cursor:pointer}
.board-table td.pts{font-weight:var(--fw-bold);color:var(--text-strong)}
/* Unfolded player row (widgets): a light grey band across the row, the content
   starting under the nickname column. Facts sit in one line where there is room
   and stack as label/value rows on phones. */
.board-table tr.player-detail td{white-space:normal;text-align:left;padding:14px 12px 16px;background:transparent;border-bottom:1px solid var(--border-subtle);cursor:default}
.board-table tr.player-detail.alt td{background:var(--surface-zebra)}
.board-table tr.player-detail:hover td{background:transparent}
.board-table tr.player-detail.alt:hover td{background:var(--surface-zebra)}
.board-table tr.player-detail .player-badge{font-size:var(--fs-13);color:var(--text-muted);margin:0}
.board-table tr.player-detail .player-facts{display:flex;flex-direction:column;margin-top:8px;font-size:var(--fs-13)}
.board-table tr.player-detail .fact{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--border-subtle)}
.board-table tr.player-detail .fact:last-child{border-bottom:none}
.board-table tr.player-detail .fact b{font-weight:var(--fw-bold);color:var(--text-strong);margin-right:6px}
.board-table tr.player-detail .player-facts tr:last-child td{border-bottom:none}
/* Ranking rows alternate white and light grey (decision of 28 Aug 2026, the medal
   tints for places 1 to 3 are gone, the medals themselves stay). The unfolded
   player row shares its row's colour, the row border is the divider. */
.board-table tbody tr.alt td{background:var(--surface-zebra)}
/* Rank medals (decision of 28 Aug 2026): flat discs, gold in the brand yellow, silver
   and bronze as soft tints, a hairline edge in a darker tone, dark numerals. */
.medal{display:inline-flex;width:24px;height:24px;border-radius:50%;align-items:center;justify-content:center;font-size:var(--fs-11);font-weight:var(--fw-extrabold);line-height:1;padding-top:1px;box-sizing:border-box;border:1px solid transparent}
.medal.m1{background:var(--medal-gold-bg);color:var(--medal-gold-text);border-color:var(--medal-gold-edge)}
.medal.m2{background:var(--medal-silver-bg);color:var(--medal-silver-text);border-color:var(--medal-silver-edge)}
.medal.m3{background:var(--medal-bronze-bg);color:var(--medal-bronze-text);border-color:var(--medal-bronze-edge)}
/* Neutral mark for places 4+ in the player profile; the tables keep the plain number. */
.medal.mn{background:var(--surface-card);color:var(--text-strong);border-color:var(--border-input)}
/* Player profile head (modal and unfolded row): mark, name, badge line. */
.player-head{display:flex;align-items:center;gap:12px}
.player-head .medal{flex:0 0 auto;width:28px;height:28px;font-size:var(--fs-12-5)}
.player-head .player-name{font-size:var(--fs-r110);font-weight:var(--fw-bold);text-transform:none;margin:0;line-height:1.3}
.modal .player-badge{font-size:var(--fs-13);color:var(--text-muted);margin:10px 0 0}
.empty-state{padding:40px 24px;text-align:center;color:var(--text-muted);font-size:var(--fs-14-5)}
/* Board area while the live data loads, and when the first load fails (30 Aug 2026). */
.loading-state{padding:40px 24px;text-align:center;color:var(--text-muted);font-size:var(--fs-14-5)}
.loading-state .spinner{display:inline-block;width:20px;height:20px;border:3px solid var(--surface-accent-tint);border-top-color:var(--accent);border-radius:50%;vertical-align:-5px;margin-right:10px;animation:epm-spin .8s linear infinite}
@keyframes epm-spin{to{transform:rotate(360deg)}}
.load-error{padding:32px 24px;text-align:center;color:var(--text-body);font-size:var(--fs-14-5);line-height:1.6}
.load-error .btn{margin-top:14px}
.dim{color:var(--text-muted)}
.board-foot{padding:10px 20px;border-top:1px solid var(--border-subtle);font-size:var(--fs-12);color:var(--text-muted);display:flex;gap:16px;flex-wrap:wrap}

.info-callout{display:flex;gap:12px;background:var(--surface-info);border-color:var(--border-info);padding:13px 16px;font-size:var(--fs-13-5);margin-bottom:18px;align-items:flex-start}
.info-callout .ic{flex:0 0 auto;color:var(--info-accent);margin-top:2px}

.chip,.badge-chip,.focus-chip,.streak-chip{border-radius:var(--radius-md);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:var(--ls-03)}
.badge-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 11px;font-size:var(--fs-11-5);color:var(--text-inverse)}
.badge-chip.bronze{background:var(--badge-bronze)} .badge-chip.silber{background:var(--badge-silver)}
.badge-chip.gold{background:var(--badge-gold-deep)}
/* Champion chip mirrors the champion card: brand black with the yellow edge. */
.badge-chip.platin{background:var(--surface-inverse);color:var(--accent);border:1px solid var(--accent-edge)}
.badge-chip.none{background:var(--surface-muted);color:var(--text-muted);border:1px solid var(--border-input)}
.badge-chip.sm{font-size:var(--fs-11);padding:2px 8px}
.stars{color:var(--accent-text);letter-spacing:var(--ls-stars);font-weight:var(--fw-bold)}
.focus-chip{display:inline-block;padding:2px 9px;font-size:var(--fs-11);border:1px solid var(--border-input);color:var(--text-body);background:var(--surface-input)}
.streak-chip{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;font-size:var(--fs-11);background:var(--status-success-soft-bg);color:var(--status-success-soft-text);border:1px solid var(--status-success-soft-border)}
.streak-chip .ico{width:1em;height:1em}

.progress-outer{height:8px;border-radius:var(--radius-pill);background:var(--surface-muted);overflow:hidden;min-width:90px}
.progress-inner{height:100%;border-radius:var(--radius-pill);background:var(--accent)}
.progress-inner.done{background:var(--status-success-fill)}

.bars{display:grid;gap:10px}
.bar-row{display:grid;grid-template-columns:170px 1fr 60px;gap:12px;align-items:center;font-size:var(--fs-13-5)}
.bar-track{height:12px;background:var(--surface-muted);border-radius:var(--radius-bar);overflow:hidden}
.bar-fill{height:100%;background:var(--accent)}
.bar-fill.alt{background:var(--info-accent)}
.bar-val{text-align:right;font-weight:var(--fw-bold)}

/* ---------- Modals ---------- */
.modal-back{position:fixed;inset:0;background:var(--surface-backdrop);display:none;align-items:flex-start;justify-content:center;padding:6vh 18px;z-index:100;overflow-y:auto}
.modal-back.open{display:flex}
.modal{background:var(--surface-raised);border-radius:var(--radius-lg);max-width:640px;width:100%;padding:28px;position:relative;box-shadow:var(--shadow-modal);margin:auto}
.modal .modal-actions{margin-top:22px;text-align:center}
.modal h3{margin-bottom:6px}
.modal .close-x{position:absolute;top:14px;right:16px;background:none;border:none;font-size:var(--fs-22);color:var(--text-muted);cursor:pointer}
/* Player modal: a profile card that reads like the step-6 summary. Name one step
   above body size, badge line muted, facts as the label/value list. */
#playerModal .modal{max-width:480px}
.modal .player-facts{margin-top:18px}
.modal .player-facts td{padding-top:8px;padding-bottom:8px}
textarea.code{width:100%;font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;font-size:var(--fs-12-5);background:var(--surface-inverse);color:var(--text-code);border:none;border-radius:var(--radius-md);padding:14px;min-height:150px;margin-top:12px;line-height:1.5}
.modal .row{display:flex;gap:10px;margin-top:12px;flex-wrap:wrap}
.modal .row .f-group{flex:1;min-width:110px}

/* ---------- Form ---------- */
.form-shell{max-width:760px;margin:0 auto}
/* Intro block above the two forms (hidden in embed mode, see the embed rules). */
.form-intro{text-align:center;margin-top:10px}
.form-intro h1{font-size:var(--fs-h1-form)}
.form-intro p{margin-top:12px;color:var(--text-muted);font-size:var(--fs-15)}
h1.dash-title{font-size:var(--fs-h1-dash)}
.form-err{display:none;margin-top:12px;color:var(--status-danger-text-strong);font-size:var(--fs-13)}
/* The standalone form adopts the widgets' message format (EPM-77, Sebastian's
   call of 10 Sep: centred and bold at the footer message size), plus his two
   additions: vertically centred in its slot (symmetric margins instead of the
   top-only 12px) and more air around the text. Scoped to the standalone page:
   embed mode keeps its own tuned bar spacing (see the html.embed rules). */
html:not(.embed) .form-err{text-align:center;font-weight:var(--fw-bold);font-size:var(--footer-err-text);margin:16px 0;padding:8px 0}
.copy-ok{display:none;color:var(--status-success-text);font-size:var(--fs-13);align-self:center;font-weight:var(--fw-bold)}
.accent-text{color:var(--accent-text)}
.demo-note{font-size:var(--fs-12-5);color:var(--text-muted);margin-top:22px}
.status-done{color:var(--status-success-text);font-weight:600}
.board-body{padding:20px}
.board-head .actions select{min-width:180px}
.progress-steps{display:flex;gap:6px;margin:26px 0 22px}
.p-step{flex:1;height:5px;border-radius:var(--radius-pill);background:var(--surface-track)}
.p-step.done{background:var(--accent)}
.form-card{padding:38px 32px 32px}
.form-card h2{font-size:var(--fs-r130);margin-bottom:18px}
.form-card .sub{color:var(--text-muted);font-size:var(--fs-14-5);margin-bottom:22px}
.field{margin-bottom:18px}
.field label.f-label{display:block;font-size:var(--fs-14);font-weight:var(--fw-bold);color:var(--text-strong);margin-bottom:6px}
.field .hint{font-size:var(--fs-12-5);color:var(--text-muted);margin-top:5px}
.field .err{display:none;font-size:var(--fs-12-5);color:var(--status-danger-text);margin-top:5px;font-weight:var(--fw-medium)}
.field.invalid .err{display:block}
.field.invalid input{border-color:var(--status-danger-border)}
.choice-grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.choice{border:1.5px solid var(--border-input);border-radius:var(--radius-md);background:var(--surface-input);color:var(--text-strong);padding:16px;cursor:pointer;transition:.2s var(--ease);text-align:left;font-size:var(--fs-15)}
.choice:hover{border-color:var(--border-strong)}
.choice.selected{border:2.5px solid var(--accent);background:var(--surface-accent-tint)}
.choice .c-title{font-weight:var(--fw-bold);display:block;font-size:var(--fs-13-5)}
.choice .c-sub{font-size:var(--fs-12-5);color:var(--text-muted);display:block;margin-top:4px;text-transform:none;font-weight:var(--fw-regular)}
.choice .c-ico{display:block;margin-bottom:10px;color:var(--text-strong)}
.choice .c-ico .ico{width:24px;height:24px}
.num-row{display:grid;grid-template-columns:1fr auto;gap:14px;align-items:center;padding:12px 0;border-bottom:1px solid var(--border-subtle)}
.num-row:last-child{border-bottom:none}
.num-row .q{font-size:var(--fs-14-5);color:var(--text-strong);font-weight:var(--fw-medium)}
.num-row .ptval{font-size:var(--fs-12);color:var(--text-muted);display:block;margin-top:2px;font-weight:var(--fw-regular)}
.num-row input{text-align:center;font-size:var(--fs-16);font-weight:var(--fw-bold)}
/* Stepper around the count (EPM-92): tap targets at 44px, typing still works,
   the minus is disabled at zero. */
.stepper{display:flex;align-items:center;gap:8px}
.stepper input{width:64px}
.step-btn{width:44px;height:44px;flex:0 0 auto;border:1px solid var(--border-input);border-radius:var(--radius-md);background:var(--surface-input);color:var(--text-strong);font-size:20px;line-height:1;cursor:pointer;transition:.2s var(--ease)}
.step-btn:hover{border-color:var(--border-strong)}
.step-btn:disabled{opacity:.4;cursor:default}
.phase-block{margin-top:24px}
.phase-block>h3{font-size:var(--fs-r092);color:var(--text-strong);padding-bottom:8px;border-bottom:2px solid var(--accent);margin-bottom:4px;letter-spacing:var(--ls-06);text-transform:uppercase}
/* The points strip (steps 4 to 6): quiet type, but its own block. It stands
   34px clear of the list above (the list rows are 22px apart), has some height
   of its own and a visible edge, so it does not read as one more list row. */
.points-strip,.live-sum,.sum-points tfoot .total td{background:var(--surface-accent-soft);color:var(--text-body);font-size:var(--fs-12);text-transform:uppercase;letter-spacing:var(--ls-08);font-weight:var(--fw-bold)}
.live-sum{border:1px solid var(--border-accent-soft);border-radius:var(--radius-sm);margin-top:34px;padding:var(--strip-pad-y) var(--strip-pad-x);display:flex;justify-content:space-between;align-items:center}
/* Label and value share size, weight and colour (decision of 28 Aug 2026). */
.live-sum b{font-weight:var(--fw-bold);white-space:nowrap}
.live-sum .lbl-short{display:none}
/* Wraps the buttons and, in step 5, the validation message. `display:contents`
   keeps it out of the layout everywhere except when it becomes the pinned
   footer in a widget, so the standalone page and every short step are
   untouched by its existence. */
.form-foot{display:contents}
.form-nav{display:flex;justify-content:space-between;align-items:center;margin-top:38px;gap:12px}
/* Turnstile sits in the button row at its native size. Scaling it with a CSS
   transform renders the iframe blurry and throws off its inner spacing. */
.ts-box{flex:0 0 auto}
.sum-table{width:100%;border-collapse:collapse;font-size:var(--fs-14);margin-top:14px}
.sum-table th{text-align:left;font-size:var(--fs-11);letter-spacing:var(--ls-06);color:var(--text-strong);padding:8px 10px;border-bottom:1px solid var(--border-strong)}
.sum-table td{padding:8px 10px;border-bottom:1px solid var(--border-subtle);color:var(--text-body)}
.sum-table td:last-child,.sum-table th:last-child{text-align:right}
/* Outer cells align with the card's heading and text: no padding on the outside.
   The highlighted total keeps its inset so the text does not touch the box edge. */
.sum-table th:first-child,.sum-table td:first-child{padding-left:0}
.sum-table th:last-child,.sum-table td:last-child{padding-right:0}
/* Step 6 points table: the number columns sit centred under their headers.
   Written with the element so it outranks the last-child right alignment. */
.sum-points th.mid,.sum-points td.mid{text-align:center}
/* Same optical air above and below the label table, measured text edge to text
   edge: the first row's cell padding and the subtitle's line-height sit above,
   only the header's padding below, so the top margin is smaller. */
.sum-meta,.kv-table{margin-top:31px}
.sum-points{margin-top:36px;border-collapse:separate;border-spacing:0}
/* Step 6 total: the same strip as on steps 4 and 5, but built as a table footer
   behind a spacer row, so the total sits in the Punkte column of the rows above.
   Keep the values in sync with .live-sum. */
.sum-points tfoot .spacer td{padding:0;height:34px;border:0}
.sum-points tfoot .total td{border:0;border-top:1px solid var(--border-accent-soft);border-bottom:1px solid var(--border-accent-soft);padding-top:var(--strip-pad-y);padding-bottom:var(--strip-pad-y);white-space:nowrap}
.sum-points tfoot .total td:first-child{border-left:1px solid var(--border-accent-soft);border-radius:var(--radius-sm) 0 0 var(--radius-sm);padding-left:var(--strip-pad-x)}
.sum-points tfoot .total td:last-child{border-right:1px solid var(--border-accent-soft);border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.sum-points .lbl-short{display:none}
/* Step 6: the entry as a label/value list. Labels bold, values right-aligned. */
.sum-meta td,.kv-table td{padding:9px 10px;vertical-align:top}
.sum-meta td:first-child,.kv-table td:first-child{width:1%;font-weight:var(--fw-bold);color:var(--text-strong);white-space:nowrap}
.sum-meta td:last-child,.kv-table td:last-child{text-align:right;color:var(--text-body);word-break:break-word}
.confirm-hero{text-align:center;padding:26px 10px}
.confirm-hero .big{margin-bottom:16px;color:var(--status-success-fill)}
.confirm-hero .big .ico{width:56px;height:56px;stroke-width:1.6}
.confirm-hero .sub{margin-top:12px}
.confirm-hero .hero-cta{justify-content:center;margin-top:26px}

/* No top margin since EPM-90: the welcome page ends in the black closing band,
   and the footer's yellow edge is the divider between the two black planes. */
.site-footer{background:var(--surface-inverse);color:var(--white-a75);border-top:3px solid var(--accent);padding:28px 24px;text-align:center;font-size:var(--fs-13)}
.site-footer strong{color:var(--accent);text-transform:uppercase;letter-spacing:var(--ls-08)}
/* Below 900px the nav row becomes the burger menu (EPM-90, absorbs EPM-51):
   the four labels never fit a phone header, and wrapping tabs ate 200px. */
@media (max-width:900px){
  .main-tabs{display:none}
  .burger{display:flex}
}
@media (max-width:720px){
  .header-inner{gap:12px}
  /* Board controls drop under the title instead of hugging the right edge
     (Sebastian, 13 Sep: heading left, field right read as misaligned). */
  .board-head .actions{margin-left:0;flex-basis:100%}
  .board-head .actions select{width:100%;min-width:0}
  /* Mobile centring of the steps heading (Sebastian, 11 Sep). */
  .section-head.center-sm{text-align:center;margin-left:auto;margin-right:auto}
  .section-head.center-sm h2::after{margin-left:auto;margin-right:auto}
  .pad{padding:20px}
  .form-card{padding:28px 22px 22px}
  /* Smaller type on phones: heading and subtitle step down, the heading gets
     more air below it, and the step-6 tables use a smaller size. */
  .form-card h2{font-size:var(--fs-r110);margin-bottom:16px}
  .form-card .sub{font-size:var(--fs-13-5);margin-bottom:20px}
  .sum-table{font-size:var(--fs-12-5)}
  .sum-meta,.kv-table{margin-top:29px}
  .sum-points{margin-top:34px}
  .sum-table th{font-size:var(--fs-10);padding:7px 8px}
  .sum-table td{padding:7px 8px}
  .sum-meta td,.kv-table td{padding:8px}
  .num-row{grid-template-columns:1fr auto}
  .stepper{gap:6px}
  .stepper input{width:52px}
  /* The points strip keeps to one line on phones: short label, value beside it. */
  .points-strip,.live-sum,.sum-points tfoot .total td{font-size:var(--fs-10-5)}
  .live-sum{margin-top:30px;padding:9px 14px;gap:10px}
  .sum-points tfoot .spacer td{height:30px}
  .sum-points tfoot .total td{padding-top:9px;padding-bottom:9px}
  .sum-points tfoot .total td:first-child{padding-left:14px}
  .sum-points .lbl-long{display:none}
  .sum-points .lbl-short{display:inline}
  .live-sum .lbl-long{display:none}
  .live-sum .lbl-short{display:inline}
  /* Form buttons stack in full width on phones, primary on top, so long labels
     no longer wrap into three lines next to a one-line "Zurück". */
  .form-nav{flex-direction:column-reverse;align-items:stretch;gap:10px}
  .form-nav .btn{justify-content:center;margin-left:0}
  .form-nav > span:empty{display:none}
}
/* Top-10 at narrow widths (Mighty's column, phones): fewer columns instead of a
   horizontal scrollbar. "Aktive Tage" and "Letzte Aktivität" stay in the full
   table and in the player detail modal. */
@media (max-width:760px){
  #board-gesamt-top10 table.board-table{min-width:0}
  #board-gesamt-top10 .board-table th:nth-child(n+6),#board-gesamt-top10 .board-table td:nth-child(n+6){display:none}
}
@media (max-width:520px){
  #board-gesamt-top10 .board-table th:nth-child(4),#board-gesamt-top10 .board-table td:nth-child(4),
  #board-gesamt-top10 .board-table th:nth-child(5),#board-gesamt-top10 .board-table td:nth-child(5){display:none}
}

/* Reduced motion: no transitions, no lifting buttons. Nothing here is visible in
   a static screenshot. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:0s!important;animation-duration:0s!important}
  html{scroll-behavior:auto}
  .btn.primary:hover{transform:none}
}

/* ---------- Embed mode (/widget/<name>, iframes in Mighty) ----------
   The class is set on <html> before the first paint (see <head>). Only the page
   frame is hidden and the width limits are lifted. The content is the same
   markup and JS as on the standalone page, so every rule here must carry the
   html.embed prefix: without the class nothing may change. */
/* Transparent on purpose: a widget is a card inside the host page, not a page.
   The iframe height is fixed (Mighty allows no resize script), so whatever the
   content does not fill would otherwise stand there as a slab in the widget's
   own page colour - up to 220px under the registration form on a wide column.
   Transparent lets the host page show through instead. Everything a widget
   renders sits on .card/.form-card, which keep their own surface. */
html.embed body{background:var(--surface-embed)}
.embed-bar{display:none}
html.embed.with-bar .embed-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:7px 12px;background:var(--surface-inverse);border-bottom:2px solid var(--accent);color:var(--text-inverse);font-size:var(--fs-11-5);font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:var(--ls-08)}
/* Widgets never link out of the iframe (Mighty's sandbox forbids navigating the
   page and a new tab would leave the app). Where the standalone page has a
   navigation button, the widget shows a hint naming the Mighty page instead. */
html.embed .embed-hint{display:block;flex-basis:100%;font-size:var(--fs-14);color:var(--text-muted);font-weight:var(--fw-medium);text-transform:none;letter-spacing:0}
html.embed .hero-cta .embed-hint{text-align:center}
html.embed .note .embed-hint{display:inline;color:var(--text-body)}
html.embed .embed-bar a{color:var(--accent);text-decoration:none;white-space:nowrap}
/* .dash-top holds the page title, which a widget must not repeat: the Mighty
   page around it carries its own heading. It used to hold the "Zuletzt
   aktualisiert" line as well; that line is gone everywhere since EPM-69
   (Sebastian, 3 Sep 2026), because the timestamp only ever read as the moment
   the widget loaded and the Live-/Demo-Daten marker only ever said Live in
   production. Loading and failure keep their own place inside the board area
   (.loading-state, .load-error). */
html.embed .site-header,html.embed .site-footer,html.embed .mobile-menu,html.embed #page-welcome,html.embed #dashSubNav,html.embed .dash-top,html.embed .board-head .actions .btn{display:none}
html.embed .page-pad{max-width:none;padding:12px 12px 20px}
html.embed .form-shell{max-width:none}
/* The form's footer as an action bar: edge, shadow, and stuck to the bottom
   edge as long as content still lies below it. `position:sticky` with
   `bottom:0` only displaces an element when it would otherwise run out of
   view, so the bar sticks on a long step and simply sits at the card's end on
   a short one. Both look the same, and that is Sebastian's decision of 7 Sep:
   the bar shall always be a bar. Before, this hung on a class .scrolls that a
   script set after every render when the content was taller than the window.
   That produced the bug Sebastian found: the same widget showed no bar at all
   in a tall window, plus a differently styled error message. The class and
   its function markScroll went away together with that gate.
   The negative margins let the bar swallow the card's padding, on the sides
   as well as at the bottom. Without the bottom one, a strip of card remained
   under the bar: in the stuck version it lay below the fold and nobody
   noticed, at the card's end it is visible. */
html.embed .form-card .form-foot{display:block;position:sticky;bottom:0;z-index:2;
  margin:38px -32px -32px;padding:16px 32px;background:var(--surface-card);
  border-radius:0 0 var(--radius-lg) var(--radius-lg)}
html.embed .form-card .form-foot .form-nav{margin-top:0}
/* The separation towards the top differs per width, and that is not a whim.
   Narrow, the bar runs edge to edge across the full widget width and closes
   off the screen like a bottom bar; --shadow-sticky-edge is built for that
   (Sebastian's choice of 4 Sep). Its shadow sits in the narrow block further
   down, not here.
   Wide, it is a divider line, and that is final. The question has been played
   through twice; that belongs here so nobody opens it a third time:
   7 Sep, the wide shadow reached 18px and laid a grey band across the card.
   Replaced by this line, Sebastian: "sieht in der weiten Variante jetzt
   besser aus".
   9 Sep, on his question about a Material elevation, measured through and set
   to 2dp at 45 percent (5px reach, edge 216). Seen on the device and
   discarded: "auf Desktop-Breite brauchen wir nur eine dünne Trennlinie".
   The reason, the same both times: wide, the bar sits in the middle of the
   card, and in a design that otherwise uses no shadow inside a card, a shadow
   there remains a foreign body. On top of that, Material's elevation is
   computed for light from above; a shadow above a bottom bar does not occur
   in it at all, the Y values would be flipped. */
@media (min-width:721px){
  html.embed .form-card .form-foot{border-top:1px solid var(--border-subtle)}
}
/* Equal air above and below the message, measured at the glyph edges: 26px
   from the bar's top edge to the top of the type, 26px from the bottom of the
   type to the button (Sebastian's choice of 7 Sep). The 4/21 look asymmetric
   and are not: above the message additionally sit the bar's 16px of padding,
   and the message's line box is 24px tall at 15px type, so the glyphs stand
   6px below its top edge and 5px above its bottom edge.
   Why not the 38px of the rest of the form: on a phone the bar eats viewport.
   And why not tighter: 18px was barely more than the 14 that Sebastian
   reported as cramped.
   Without an error, .form-err sits at display:none, so the box including its
   outer margin drops out entirely and the bar stays at 120px. The bar's
   padding therefore stays untouched: it alone determines what the bar looks
   like without a message.
   These values are for the narrow bar. Wide they differ, see below. */
/* The message's appearance hangs on the widget, not on the stuck bar. That
   separation is the lesson of 7 Sep: the bar stuck only with the class
   .scrolls set, and because I had hung centred, bold and 15px on exactly that
   class, the same widget showed two different messages. In a tall window
   where the list fits, it fell back to 13px left-aligned, and Sebastian found
   that promptly. In Mighty's fixed-height iframe the bar sticks almost
   always, so the fallback was the exception and therefore looked like a bug.
   The standalone page stays out (no html.embed): it has no bar and its
   design is approved.
   Wide 18px instead of 15: centred between two buttons sitting far apart, the
   message got lost. Not 20px, because the buttons beside it carry 13.5px
   capitals and 20 read like a heading next to them. */
html.embed .form-foot .form-err{text-align:center;
  font-size:var(--footer-err-text);font-weight:var(--fw-bold)}
@media (min-width:721px){
  html.embed .form-foot .form-err{font-size:var(--footer-err-text-wide)}
}
/* The margins, by contrast, belong to the bar: only there is a top edge for
   something to sit symmetric to. Without the bar, the form's rhythm applies
   (12px above from the base rule, 38px below from .form-nav).
   Both values are recalculated for their own width, because two quantities
   differ between narrow and wide: wide, the bar carries 16px of padding
   instead of 12, and the line box is taller at 18px type. Without that
   calculation the wide layout had 30px above and 26px below the type, so the
   symmetry was never there - unnoticed, because the test rig only checked it
   narrow. */
html.embed .form-card .form-foot .form-err{margin:4px 0 21px}
@media (min-width:721px){
  html.embed .form-card .form-foot .form-err{margin:3px 0 20px}
}
/* On a phone the bar spans the whole widget and ends flat, the way a bottom app
   bar closes off a screen (Sebastian, 4 Sep: only there, not on a desktop,
   where it stays inside the card with its rounded corners). Spanning the widget
   means the negative margin has to swallow three things: the card's 22px of
   padding, its 1px border and the 12px of .page-pad around it, so 35. Get it
   wrong and the bar either leaves a strip of page beside it or overhangs the
   widget. This block
   sits here and not with the other max-width rules on purpose: those come
   earlier in the file than the base rule above, so an override there would lose
   and the bar would silently keep the wide padding on a phone - which is
   exactly what happened on the first attempt. The stacked, full-width shape of
   the buttons is untouched; embed-test guards it. */
/* 16px top and bottom, not 12/14: with those, a step with only one button
   showed it 2px too high, and that stands out because the shadow visually
   swallows the top spacing (Sebastian, 7 Sep). Same padding as the wide
   layout; the bar thereby becomes 74px tall instead of 68px. */
@media (max-width:720px){
  html.embed .form-card .form-foot{margin:30px -35px -23px;padding:16px;
    border-radius:0;box-shadow:var(--shadow-sticky-edge)}
}
html.embed .filterbar{margin-bottom:14px}
/* Every board is its own widget (decision of 30 Aug 2026, EPM-64): the pill bar
   that switches the channel stays on the standalone page only. */
html.embed .pills{display:none}
/* Compact area widgets: no update line, no board description (the Mighty page
   carries the heading; several boards stack on one page). */
html.embed .compact-board .board-head .desc{display:none}
/* Mighty's standard embed column is about 640px wide: four KPI tiles must
   still share one row there (two by two on phones). */
html.embed .tiles{grid-template-columns:repeat(auto-fit,minmax(135px,1fr));gap:10px}
/* Inside an iframe position:fixed means the iframe box, not the reader's screen, and
   the host page cannot be scrolled from here. The backdrop covers the whole widget
   document and placeModal() centres the card on the tapped point. */
html.embed .modal-back{position:absolute;inset:auto;top:0;left:0;right:0;padding:0 18px;overflow:visible}
html.embed .modal{margin:0 auto}
html.embed .tile{padding:14px 14px}
html.embed .tile .t-value{font-size:var(--fs-r1375)}
html.embed .embed-view{text-align:center;padding:2px 0 10px}
/* Form widgets: the Mighty page carries the heading, so the intro block (badge,
   heading, note) above the two forms is hidden. */
html.embed #page-register .form-shell>div:first-child,html.embed #page-submit .form-shell>div:first-child{display:none}
