/* The look of the page, "Contrology": a 1930s-40s Pilates studio archive, in
   paper, ink, oxblood and brass, with ruled lines and numbered plates. The
   themes, the layout and the print rules. Every element styles itself in its
   fragment and reads these custom properties, which inherit into shadow
   roots. */

/* The fonts are self-hosted (assets/static/fonts/, with their licences). */
@font-face {
  font-family: "Source Sans 3";
  src: url("/fonts/source-sans-3.woff2") format("woff2");
  font-weight: 200 900;
  font-display: swap;
}

@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces-italic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("/fonts/jost.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

/* The colour theme is chosen by `data-theme` on <html> (src/theme.mjs); without
   it the default, paper, applies. A theme's attribute selector beats the bare
   `:root`, and its dark block comes later than the light ones. */
:root {
  color-scheme: light dark;
  --radius: 3px;
  /* The style defaults, Archive (the Seal block below overrides them): the
     header on the page colour, the secondary buttons on the panel, the
     browser's toolbar in the accent. */
  --header-bg: var(--bg);
  --header-text: var(--text);
  --header-muted: var(--muted);
  --header-mark: var(--accent);
  --button-bg: var(--panel);
  --button-border: var(--border);
  /* Archive: the status badges (Open now, Built-in) are inked outlines, like
     the double-ring stamp. */
  --badge-bg: transparent;
  --badge-border: var(--accent);
  --badge-text: var(--accent);
  --browser-color: var(--accent);
  /* Source Sans 3 for the text, Fraunces (set sharp) for the headings and the
     exercise names, Jost (a free Futura) for the labels: uppercase, tracked.
     The fragments use --font-head, --font-head-weight, --font-head-axes,
     --font-label, --label-weight and --label-tracking and never name a
     font. */
  --font-body: "Source Sans 3", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-head: "Fraunces", Georgia, serif;
  --font-head-weight: 480;
  --font-head-axes: "SOFT" 0, "WONK" 0;
  --font-label: "Jost", var(--font-body);
  --label-weight: 500;
  --label-tracking: .14em;
  /* The colours of the eight categories, in the order of CATEGORIES, the same
     in every theme: deep here, bright in dark mode, each at least 3:1 against
     the panels. */
  --cat-1: #b07c12;
  --cat-2: #b4502e;
  --cat-3: #33709f;
  --cat-4: #4d8732;
  --cat-5: #7a52a8;
  --cat-6: #1f8276;
  --cat-7: #b84a70;
  --cat-8: #7f7562;
  /* The figure of the position pictograms (the Library), mixed from each
     theme's colours, so every theme, light and dark, gets its own: skin from
     the warm category colours, a top in the accent, leggings near the text
     colour, dark hair. */
  --figure-skin: color-mix(in srgb, var(--cat-1) 45%, var(--cat-2));
  --figure-top: var(--accent);
  --figure-legs: color-mix(in srgb, var(--text) 75%, var(--accent));
  --figure-hair: color-mix(in srgb, var(--cat-2) 25%, #2b211c);
  /* The level plants of the Library (seedling, sapling, tree), mixed from each
     theme's colours too: the green (--cat-4) gets fuller with the level, the
     tree has a warm trunk and blossoms. */
  --plant-soil: var(--muted);
  --plant-1-ink: color-mix(in srgb, var(--cat-4) 55%, var(--text));
  --plant-1-leaf: color-mix(in srgb, var(--cat-4) 35%, var(--panel));
  --plant-2-ink: color-mix(in srgb, var(--cat-4) 45%, var(--text));
  --plant-2-leaf: color-mix(in srgb, var(--cat-4) 70%, var(--panel));
  --plant-3-ink: color-mix(in srgb, var(--cat-4) 35%, var(--text));
  --plant-3-leaf: color-mix(in srgb, var(--cat-4) 85%, var(--text));
  --plant-3-trunk: color-mix(in srgb, color-mix(in srgb, var(--cat-1) 45%, var(--cat-2)) 65%, var(--text));
  --plant-3-blossom: color-mix(in srgb, var(--cat-7) 70%, var(--panel));
}

/* Per theme: --rule is the ink of the ruled lines, --highlight the brass of
   the plate numbers (used as text); the --player-* colours are the class
   player's, dark in every theme and mode. */
:root,
:root[data-theme="paper"] {
  --bg: #e8ddc8;
  --panel: #fffcf6;
  --text: #17130f;
  --muted: #594e42;
  --border: #c2ae8e;
  --rule: #17130f;
  --accent: #7b2d26;
  --accent-text: #fffcf6;
  --accent-soft: #ecc8bc;
  --highlight: #7a5412;
  --warn: #a14a12;
  --warn-soft: #f9e3d1;
  --track: #dccdb2;
  --focus: #2c5d8a;
  --player-bg: #16120f;
  --player-text: #f3ece0;
  --player-muted: #a89c8c;
  --player-accent: #d8b46e;
  --player-track: #2e2822;
}

:root[data-theme="studio"] {
  --bg: #dce3d4;
  --panel: #fcfdf9;
  --text: #131a15;
  --muted: #515c53;
  --border: #aebba6;
  --rule: #131a15;
  --accent: #2e5440;
  --accent-text: #fcfdf9;
  --accent-soft: #c2dbc9;
  --highlight: #775612;
  --warn: #9c4128;
  --warn-soft: #f3d6ca;
  --track: #cdd6c4;
  --focus: #2c5d8a;
  --player-bg: #101712;
  --player-text: #e8eee6;
  --player-muted: #9ba89d;
  --player-accent: #d8b46e;
  --player-track: #26302a;
}

:root[data-theme="night"] {
  --bg: #dbe0ec;
  --panel: #fcfdff;
  --text: #10162a;
  --muted: #4d566c;
  --border: #aab4cb;
  --rule: #10162a;
  --accent: #263f73;
  --accent-text: #fcfdff;
  --accent-soft: #c6d3ef;
  --highlight: #775612;
  --warn: #a3452c;
  --warn-soft: #f7e1d8;
  --track: #cbd2e2;
  --focus: #6b3fa0;
  --player-bg: #0d111c;
  --player-text: #e6eaf4;
  --player-muted: #98a1b7;
  --player-accent: #dcb96f;
  --player-track: #232b3d;
}

@media (prefers-color-scheme: dark) {
  :root {
    --cat-1: #e6b24e;
    --cat-2: #ec8460;
    --cat-3: #72aade;
    --cat-4: #8cc46a;
    --cat-5: #b595e2;
    --cat-6: #5cc2b2;
    --cat-7: #ee8fb0;
    --cat-8: #ddd1b8;
  }

  :root,
  :root[data-theme="paper"] {
    --bg: #110e0b;
    --panel: #272019;
    --text: #f7f0e4;
    --muted: #b8aa96;
    --border: #574a3c;
    --rule: #f7f0e4;
    --accent: #f08f7b;
    --accent-text: #2a0f0a;
    --accent-soft: #612b21;
    --highlight: #e6bd6a;
    --warn: #f7a468;
    --warn-soft: #5a331b;
    --track: #3d3329;
    --focus: #9cc3df;
    --player-bg: #16120f;
    --player-text: #f3ece0;
    --player-muted: #a89c8c;
    --player-accent: #d8b46e;
    --player-track: #2e2822;
  }

  :root[data-theme="studio"] {
    --bg: #0c110d;
    --panel: #1d2720;
    --text: #edf3ec;
    --muted: #a8b6a9;
    --border: #435245;
    --rule: #edf3ec;
    --accent: #84d1a4;
    --accent-text: #0c2116;
    --accent-soft: #23472f;
    --highlight: #e2bc68;
    --warn: #f2a08a;
    --warn-soft: #563026;
    --track: #2d3a30;
    --focus: #9cc3df;
    --player-bg: #101712;
    --player-text: #e8eee6;
    --player-muted: #9ba89d;
    --player-accent: #d8b46e;
    --player-track: #26302a;
  }

  :root[data-theme="night"] {
    --bg: #090d17;
    --panel: #192134;
    --text: #edf1fa;
    --muted: #a5aec5;
    --border: #3d4866;
    --rule: #edf1fa;
    --accent: #93b3f6;
    --accent-text: #0c1630;
    --accent-soft: #273965;
    --highlight: #e4be6c;
    --warn: #f2a08a;
    --warn-soft: #53302a;
    --track: #2a344d;
    --focus: #d0a8f0;
    --player-bg: #0d111c;
    --player-text: #e6eaf4;
    --player-muted: #98a1b7;
    --player-accent: #dcb96f;
    --player-track: #232b3d;
  }
}

/* The style is chosen by `data-style` on <html> (src/theme.mjs), always set:
   archive (the defaults above) or seal, a modern variant with the header on a
   solid colour band, rounder corners, soft-filled secondary buttons and solid
   status badges. It comes after the theme blocks and only sets the style's own
   properties, which the themes do not define. In dark mode the band is the
   soft accent, so the header text is the text colour. */
:root[data-style="seal"] {
  --radius: 8px;
  --header-bg: var(--accent);
  --header-text: var(--accent-text);
  --header-muted: color-mix(in srgb, var(--header-text) 82%, var(--header-bg));
  --header-mark: var(--header-text);
  --button-bg: var(--accent-soft);
  --button-border: var(--accent-soft);
  /* Seal: the status badges are solid, like the band stamp. */
  --badge-bg: var(--accent);
  --badge-border: var(--accent);
  --badge-text: var(--accent-text);
  --browser-color: var(--header-bg);
}

@media (prefers-color-scheme: dark) {
  :root[data-style="seal"] {
    --header-bg: var(--accent-soft);
    --header-text: var(--text);
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font: 15px/1.45 var(--font-body);
  background: var(--bg);
  color: var(--text);
}

h1,
h2 {
  margin: 0;
}

a {
  color: var(--accent);
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* The header, on the style's tokens. Archive: on the page colour, with a
   print-style double rule under it, a 1px line, a 2px gap and a 3px line (the
   border and the pseudo-element). Seal: a solid band, no rules (below). */
header {
  position: relative;
  margin-bottom: 6px;
  background: var(--header-bg);
  border-bottom: 1px solid var(--rule);
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 3px;
  background: var(--rule);
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The wordmark: the figure of the icon, then the title as a label, with the
   tagline under it in the body font. Phones first: the title stays on one line
   beside the two switches; wider screens are below the Seal rules. */
header h1 {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  white-space: nowrap;
  color: var(--header-text);
  font-family: var(--font-label);
  font-weight: var(--label-weight);
  font-size: .8rem;
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
}

header h1 .wordmark {
  display: grid;
  gap: 1px;
  min-width: 0;
}

header h1 small {
  color: var(--header-muted);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: .72rem;
  letter-spacing: .02em;
  text-transform: none;
}

header h1 svg {
  flex: none;
  width: 24px;
  height: 24px;
  color: var(--header-mark);
}

/* Seal: the band has no rules; the wordmark is Fraunces in tracked capitals,
   the tagline Fraunces italic. The header switches get a light border, which
   shows on the band. */
:root[data-style="seal"] header {
  --switch-border: var(--header-text);
  margin-bottom: 0;
  border-bottom: 0;
  padding: 14px 12px;
}

:root[data-style="seal"] header::after {
  content: none;
}

:root[data-style="seal"] header h1 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: .85rem;
  letter-spacing: .06em;
  font-variation-settings: var(--font-head-axes);
}

:root[data-style="seal"] header h1 small {
  font-family: var(--font-head);
  font-style: italic;
  font-weight: 500;
  font-size: .8rem;
  letter-spacing: .01em;
  font-variation-settings: var(--font-head-axes);
}

/* Wider than a phone: more padding and a larger, more tracked title. */
@media (min-width: 481px) {
  header {
    padding: 12px 20px;
  }

  header h1 {
    gap: 10px;
    font-size: 1.05rem;
    letter-spacing: .2em;
  }

  :root[data-style="seal"] header {
    padding: 14px 20px;
  }

  :root[data-style="seal"] header h1 {
    font-size: 1.15rem;
    letter-spacing: .1em;
  }
}

/* Extra spacing on phones: the fragments add these to their base padding and
   gaps with calc(), and from 481px they are 0, so wider screens keep the
   denser layout. */
:root {
  --room-s: 2px;
  --room-m: 4px;
  --room-l: 6px;
}
@media (min-width: 481px) {
  :root {
    --room-s: 0px;
    --room-m: 0px;
    --room-l: 0px;
  }
}

main {
  display: grid;
  gap: 16px;
  padding: 12px;
}

/* The footer with the links to the privacy notice and the Impressum
(fragments/legal-footer.html), on every page. */
footer {
  margin: 8px 20px 24px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
  font-family: var(--font-label);
  font-weight: var(--label-weight);
  font-size: .8rem;
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
}
footer nav {
  display: flex;
  justify-content: center;
  gap: 20px;
}
footer a {
  padding: 8px 0;
  color: var(--muted);
}

@media (min-width: 801px) {
  main {
    padding: 16px 20px;
  }
}

/* Until the module defines <tab-panels>, its sections would show one under
   the other and then two would close: the page jumped. They stay hidden until
   then, in a screen's height that keeps the footer below. */
tab-panels:not(:defined) {
  display: block;
  min-height: 100vh;
}
tab-panels:not(:defined) > section {
  display: none;
}

tab-panels {
  --tab-panels-accent: var(--accent);
  --tab-panels-border: var(--border);
  --tab-panels-gap: 16px;
  --tab-panels-selected-weight: 600;
}

/* The tab labels are labels; no font-weight here, or this rule would beat the
   selected tab's (a tab not selected keeps the normal weight). */
tab-panels::part(tab) {
  font-family: var(--font-label);
  font-size: .85rem;
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
}

/* The dropdown that replaces the tabs when they do not fit, like the labels. */
tab-panels::part(select) {
  font-family: var(--font-label);
  font-size: .85rem;
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
  background: var(--panel);
  border: 1px solid var(--border);
  border-bottom: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 0 12px;
  accent-color: var(--accent);
}

/* Phones: always the dropdown, even when the tabs would fit (user,
   2026-11-08). On a screen only: print shows neither. Stays max-width: it
   overrides the component's own display logic, which a min-width query could
   not restore from outside. */
@media screen and (max-width: 480px) {
  tab-panels::part(tablist) {
    display: none;
  }

  tab-panels::part(select) {
    display: block;
  }
}

/* The class editor, in the Classes tab in place of the list (pilates.mjs): one
   column of the totals, the recipe and the sequence; the Add exercises dialog
   (#pick-dialog, below) is what the sequence's Add button opens. The recipe
   editor, in the Recipes tab, is one column too. */
#class:not([hidden]),
#recipe:not([hidden]) {
  display: grid;
  gap: calc(16px + var(--room-m));
}

/* The elements' own display: block would beat the hidden attribute. */
class-list[hidden],
recipe-list[hidden] {
  display: none;
}

/* The Add exercises dialog: <exercise-reader mode="pick"> in a modal dialog,
   which fills the screen; from 801px it is a framed box. The reader draws its
   own heading, Close button and padding. */
#pick-dialog {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  padding: 0;
  overflow: hidden;
  background: var(--panel);
  color: var(--text);
  border: 0;
  border-radius: 0;
}
@media (min-width: 801px) {
  #pick-dialog {
    width: min(60rem, calc(100% - 32px));
    height: calc(100% - 32px);
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }
}

/* "← Classes" and "← Recipes", at the top of an editor. */
.back {
  justify-self: start;
  color: var(--accent);
  padding: 4px 0;
}
@media (pointer: coarse) {
  .back {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* The collapsible "What this page does" block under each tab's heading. No
   `display` on .view-help: it would override the hidden attribute. */
.view-help {
  margin-block-end: 16px;
}
#class > .view-help,
#recipe > .view-help {
  margin-block-end: 0;
}
.view-help summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
  color: var(--muted);
  font-family: var(--font-label);
  font-weight: var(--label-weight);
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
  font-size: .75rem;
}
.view-help summary::-webkit-details-marker {
  display: none;
}
.view-help .mark {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 1px solid currentColor;
  border-radius: 50%;
  letter-spacing: 0;
}
.view-help[open] .mark {
  color: var(--accent);
}
.view-help summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.view-help p {
  margin: 8px 0 0;
  padding-block-start: 8px;
  border-block-start: 1px solid var(--border);
  max-width: 65ch;
}
@media (hover: hover) {
  .view-help summary:hover {
    color: var(--text);
  }
}
@media (pointer: coarse) {
  .view-help summary {
    min-height: 44px;
  }
}

main.not-found {
  display: block;
}

/* The stamp of the 404 page (fragments/stamp.html): the one of the page's
   style. */
.stamp svg {
  display: block;
  width: 200px;
  height: 200px;
  margin-top: 24px;
  color: var(--accent);
}

:root:not([data-style="seal"]) .stamp-seal,
:root[data-style="seal"] .stamp-archive {
  display: none;
}

.stamp text {
  font-family: var(--font-head);
  font-variation-settings: var(--font-head-axes);
}

.stamp .name {
  text-transform: uppercase;
}

:root[lang="de"] .stamp-seal .tagline {
  font-size: 30px;
}

/* Print: only the class sequence's table, which the element shows itself. */
@media print {
  body {
    background: #fff;
    color: #000;
  }

  header,
  #library,
  tab-panels > section > h2,
  class-settings,
  class-totals,
  class-player,
  recipe-editor,
  today-panel,
  #recipe,
  .back,
  .view-help,
  footer,
  noscript {
    display: none !important;
  }

  main {
    display: block;
    padding: 0;
  }

  tab-panels,
  tab-panels > section,
  #class:not([hidden]) {
    display: block;
  }
}
