/* BePünktli — foundations.
   Schweizer Verkehrsgrafik: weisses Papier, Helvetica-Grotesk, schwarze Balken,
   Verkehrsrot als Signal (nie als Dekor), Postgelb und Verkehrsblau als Verkehrsmittel.
   Alles rechtwinklig. Die Bahnhofsuhr ist die Marke.

   Carried over from the design project verbatim, with one change: the Google Fonts
   `@import` is gone. The faces are self-hosted in `fonts.css` — a public record of Swiss
   transport should not hand a third party every visitor's IP, and the print variants must
   not depend on a network fetch. */

:root{
  /* surfaces & ink — plain white, no paper tint */
  --paper:#FFFFFF; --surface:#FFFFFF; --surface-2:#F2F3F4; --surface-3:#E4E6E8;
  --ink:#000000; --ink-2:#4A4E52; --ink-3:#63686C;   /* ink-3 is the quietest text we allow: 5.3:1 on white */
  --rule:#D3D6D9; --rule-soft:#E7E9EB; --rule-strong:#000000;
  --bar:#000000;               /* the heavy black rule: section heads, boards */

  /* Signal. Verkehrsrot — reserved: the mark, the second hand, disruption, miss.
     Never a decorative fill, never a primary button (buttons are black). */
  --accent:#CC0605; --accent-ink:#B70504; --accent-soft:#FBEAE9; --accent-line:#EFA3A0;

  /* modes — the badge colours of Swiss transit */
  --mode-rail:#000000; --mode-rail-ink:#FFFFFF;      /* IC · IR · RE, black board */
  --mode-sbahn:#0069B4; --mode-sbahn-ink:#FFFFFF;    /* S-Bahn blue */
  --mode-bus:#FFCC00; --mode-bus-ink:#000000;        /* Postauto yellow */
  --mode-tram:#005EA8; --mode-tram-ink:#FFFFFF;
  --mode-metro:#00703A; --mode-metro-ink:#FFFFFF;   /* darkened from the official green: white on it must clear 4.5:1 */
  --mode-boat:#00719B; --mode-boat-ink:#FFFFFF;    /* likewise */
  --mode-cogwheel:#8C1518; --mode-cogwheel-ink:#FFFFFF;

  /* signed delay — diverging around zero. Neither end reads as good.
     Kept clear of Verkehrsrot so that red always means failure, not lateness. */
  --late:#A85400; --late-soft:#FBEEE1;
  --early:#1F5FA8; --early-soft:#E6EDF6;
  --ontime:#00704A; --ontime-soft:#E2EFE9;

  /* outcomes */
  --miss:#CC0605; --miss-soft:#FBEAE9;
  --absent:#7A8085;            /* unmeasured — always hatched, never a colour alone, never text */
  --absent-soft:#EDEFF0;

  /* the two displays on real vehicles and platforms */
  --matrix-bg:#08090A;               /* the unlit blind */
  --matrix-amber:#FFB03A;            /* Postauto / bus destination blind */
  --matrix-green:#8CEF5B;            /* S-Bahn front blind */
  --matrix-white:#EDF3FA;
  --board:#2B2E7E; --board-ink:#FFFFFF;   /* Perronanzeiger blue */

  /* type — the transport grotesk.

     **Archivo leads, and the order is the whole point.** This stack asked for Helvetica Neue
     first and put the self-hosted Archivo third, which reads as a sensible preference and is
     not one: `fc-match "Helvetica Neue"` does not *fail* on a Linux box, it **answers** —
     Nimbus Sans here, Liberation Sans in Chrome, Roboto on Android. A fallback only reaches
     the next name when the one before it is absent, so the face this project ships, hosts and
     pays two woff2 files for was never once used outside a Mac. Measured in the owner's own
     browser on 2026-09-25: the old stack rendered a test string at 633.67 px, which is
     Liberation Sans to the hundredth; Archivo sets it at 579.14. Every judgement anybody has
     made about this design's type was a judgement about Arial. */
  --font-sans:'Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  --font-display:var(--font-sans);
  --font-serif:var(--font-sans);   /* alias: this system has no serif */
  --font-mono:ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --font-dot:'Silkscreen','Helvetica Neue',monospace;   /* only inside a matrix display */

  --t-fig-xl:44px; --t-fig-l:28px; --t-fig-m:20px; --t-fig-s:15px;
  --t-h1:26px; --t-h2:19px; --t-h3:12px;
  --t-body:15px; --t-sm:13px; --t-xs:11.5px; --t-micro:10px;

  /* The name of the thing a row is *about* — the station on a spine row, the endpoint in the
     search field. Everything on a result card was set between 11.5 and 15 px, so no row had a
     subject and the eye had nowhere to land; this is the one step above running text, and it
     is spent on the two nouns the visitor came for and nowhere else. */
  --t-lead:17px;

  /* space & rule */
  --s1:2px; --s2:4px; --s3:6px; --s4:8px; --s5:12px; --s6:16px; --s7:24px; --s8:32px; --s9:48px;

  /* One height for every control on a form row. Set explicitly because the intrinsic heights
     disagree: `input[type=time]` is taller than a `select` is taller than a `button` with the
     same padding, and a row that bottom-aligns them puts their labels on three different
     lines.

     **44 and not 40**: this form is operated with a thumb on a phone (design §9), and 40 px is
     under every touch-target floor there is. The four px land inside the control, so no row
     re-flows — only the boxes grow. */
  --control-h:44px;
  --r-sm:0px; --r-md:0px; --r-lg:0px;   /* nothing in this system is rounded */
  --shadow:none;
  --shadow-lift:0 10px 30px -14px rgba(0,0,0,.45);

  /* The native controls the search form uses — the date field, the time field, the select's
     arrow — are drawn by the OS, and the OS reads this and nothing else. Without it a page
     switched to dark keeps a white time picker and an invisible select arrow. */
  color-scheme:light;
}

:root[data-theme="dark"],[data-theme="dark"]{
  --paper:#000000; --surface:#0C0D0E; --surface-2:#17191B; --surface-3:#212427;
  --ink:#FFFFFF; --ink-2:#AEB3B7; --ink-3:#80868B;
  --rule:#2C3033; --rule-soft:#1D2022; --rule-strong:#FFFFFF; --bar:#FFFFFF;
  --accent:#FF3B30; --accent-ink:#FF6259; --accent-soft:#2A0E0D; --accent-line:#8C2320;
  --mode-rail:#FFFFFF; --mode-rail-ink:#000000;
  --mode-sbahn:#2E9BE0; --mode-sbahn-ink:#000000;
  --mode-bus:#FFCC00; --mode-bus-ink:#000000;
  --mode-tram:#4E9FDA; --mode-tram-ink:#000000;
  --mode-boat:#39B3DF; --mode-boat-ink:#000000;
  --mode-cogwheel:#D8595C; --mode-cogwheel-ink:#000000;
  --late:#E3902F; --late-soft:#2A1C0A;
  --early:#79A9E3; --early-soft:#101C2B;
  --ontime:#4FB287; --ontime-soft:#0C211A;
  --miss:#FF6259; --miss-soft:#2A0E0D;
  --absent:#6E7478; --absent-soft:#1C1F21;
  --board:#1B1E5E;
  --shadow:none;
  --shadow-lift:0 10px 30px -14px rgba(0,0,0,.9);
  color-scheme:dark;
}

*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--font-sans);font-size:var(--t-body);line-height:1.42;-webkit-font-smoothing:antialiased;text-wrap:pretty}
a{color:var(--accent-ink);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
a:hover{color:var(--ink);text-decoration-color:var(--ink)}

/* Focus is Verkehrsrot and never removed — it is the one place red means "you are here". */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* figures always align */
.bp-num,.bp-fig{font-variant-numeric:tabular-nums lining-nums;font-feature-settings:"tnum" 1}

h1,h2{font-family:var(--font-display);font-weight:700;letter-spacing:-.022em;margin:0}
h1{font-size:var(--t-h1);line-height:1.1}
h2{font-size:var(--t-h2);line-height:1.15}
.bp-label{font-size:var(--t-h3);font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-2)}
.bp-mono{font-family:var(--font-mono);font-size:var(--t-xs);letter-spacing:-.01em}
.bp-rule{height:1px;background:var(--rule);border:0;margin:0}
.bp-bar{height:3px;background:var(--bar);border:0;margin:0}   /* the heavy Swiss rule */
summary::-webkit-details-marker{display:none}                 /* our own marker, never the OS triangle */

@keyframes bpPulse{0%,100%{opacity:1}50%{opacity:.45}}
/* the indeterminate rule: a loading bar has no place lying about progress, so it travels */
@keyframes bpSlide{0%{transform:translateX(-100%)}100%{transform:translateX(264%)}}
@keyframes bpWobble{0%,100%{transform:rotate(-.9deg)}50%{transform:rotate(.9deg)}}
/* the railway-clock sweep: 58.5 s of travel, then the pause at twelve */
@keyframes bpSweep{0%{transform:rotate(0deg)}97.5%{transform:rotate(360deg)}100%{transform:rotate(360deg)}}

/* Read aloud, never drawn. For the name behind a mark that carries its meaning in colour or
   shape — a mode square, a drag handle — where printing the word would crowd the row. */
.bp-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* the hatch used for every "unmeasured" surface in the system */
.bp-hatch{background-image:repeating-linear-gradient(135deg,var(--absent) 0 1px,transparent 1px 4px)}

/* The hour-of-day table's bar.
   A background on the cell, never the only encoding: the percentage is printed in the same cell,
   so the row survives greyscale, a print stylesheet that drops backgrounds, and a reader who
   cannot distinguish the hue (design/01-constraints.md §7). `--w` is set server-side; there is no
   JavaScript on these pages and this must render complete on first paint. */
.bp-hourbar{position:relative;isolation:isolate}
.bp-hourbar::before{content:"";position:absolute;inset:0 auto 0 0;width:var(--w,0%);
  background:var(--late);opacity:.18;z-index:-1}
/* The worst hour of the day is worth finding without reading every row. A rule, not a fill, so it
   reads as an annotation rather than as a second scale. */
.bp-hourbar--worst::after{content:"";position:absolute;inset:0 0 0 auto;width:2px;background:var(--miss)}
/* The weekend columns, separated by a rule rather than a fill: Saturday and Sunday are a
   different service pattern, not a different importance. */
.bp-hourgrid__end{border-left:1px solid var(--rule,currentColor)}
/* Today's column. A heavier type weight and an underline on the header, never a fill: the cells
   already carry a bar and a worst-hour rule, and a third background would make the grid a
   heatmap nobody asked for. Readable in greyscale and in print, which a colour alone is not. */
th.bp-hourgrid--today{text-decoration:underline;text-underline-offset:.3em;text-decoration-thickness:2px}
td.bp-hourgrid--today{font-weight:600}
