/* Anfield-radar — the whole design system. One file, no framework, no build step.
   Red ground, white cards, black actions, one yellow accent. Condensed uppercase for eyebrows and
   headings, Barlow for everything else. No crest, no wordmark, no club imagery anywhere: this is
   an operator's tool in the club's colours, not a fan page. */

/* --- Faces ----------------------------------------------------------------------------------
   Self-hosted latin woff2 (decision 7). font-display: swap so a cold cache shows the fallback
   immediately rather than an empty page; the fallback stack is picked to be close in width so the
   swap does not reflow the tables. */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/barlow-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/barlow-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/static/fonts/barlow-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/barlow-condensed-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/static/fonts/barlow-condensed-700.woff2') format('woff2');
}

/* --- Tokens --------------------------------------------------------------------------------- */
:root {
  --red: #c8102e;
  --red-deep: #8e0a20;
  --yellow: #f6eb61;
  --black: #111111;
  --white: #ffffff;
  --grey-100: #f4f4f4;
  --grey-300: #d9d9d9;
  --grey-600: #6b6b6b;
  /* Secondary body text on white. grey-600 is the label grey and sits at 5.33:1; this one is
     9.7:1 and is what a sentence a reader actually has to read is set in. */
  --grey-700: #4a4a4a;
  /* The one colour outside the club palette: "open, go now". Picked so that white on it and it
     on white are both 5.08:1, which red and yellow can only manage in one direction. */
  --green: #1a7f37;
  /* Text green for the open-status chip: --green on --tint-green is 4.47:1, a hair under AA, so
     the chip's text is one step darker (6.5:1). */
  --green-deep: #146329;
  /* Derived, only for the diff, the flash and the status chips: full-strength red, yellow or green
     behind body text is unreadable, and these tints are the only places the palette needs a wash. */
  --tint-red: #fbe9ec;
  --tint-yellow: #fcf9dc;
  --tint-green: #e6f4ea;

  --sans: 'Barlow', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --cond: 'Barlow Condensed', 'Barlow', 'Segoe UI Condensed', 'Arial Narrow', system-ui, sans-serif;
  --mono: ui-monospace, 'Cascadia Mono', 'Consolas', 'SFMono-Regular', 'Liberation Mono', monospace;

  --page-w: 68rem;
  --gap: 1rem;
  --gap-lg: 1.75rem;
  --radius: 2px;
  --shadow: 0 1px 0 rgb(17 17 17 / 8%), 0 8px 20px rgb(17 17 17 / 10%);
}

/* --- Ground --------------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--red);
  color: var(--black);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
}

/* The 503 and 403 pages from src/web/auth.js render before any layout exists, and the login page is
   deliberately the same ground: red, no masthead, no nav (decision 21). White text is right for the
   two hand-written pages and wrong inside the login card, which paints its own back to black. */
body.bare { padding: 2rem 0; color: var(--white); }
body.bare a { color: var(--yellow); }

.page {
  width: 100%;
  max-width: var(--page-w);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

main.page { padding-block: var(--gap-lg) 3rem; }

a { color: var(--red-deep); }
a:hover { color: var(--black); }

/* One focus ring everywhere, black on the white surfaces and yellow on the red ones. Never
   removed: this UI is driven entirely by links, buttons and form controls. */
:focus-visible {
  outline: 3px solid var(--black);
  outline-offset: 2px;
}
.masthead :focus-visible,
.foot :focus-visible { outline-color: var(--yellow); }

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  z-index: 2;
  background: var(--white);
  padding: 0.5rem 0.75rem;
}

/* --- Type ----------------------------------------------------------------------------------- */
.h1,
.h2 {
  font-family: var(--cond);
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.1;
  margin: 0;
  text-transform: uppercase;
}
.h1 { font-size: clamp(2rem, 5vw, 2.75rem); color: var(--white); }
.h2 { font-size: 1.5rem; }

/* The small condensed uppercase label above almost everything — the one typographic idea the
   whole UI is built on. */
.eyebrow {
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grey-600);
  margin: 0;
}

.muted { color: var(--grey-600); }
.pre-wrap { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0; }

/* --- Masthead and nav ----------------------------------------------------------------------- */
.masthead {
  background: var(--red-deep);
  border-bottom: 4px solid var(--yellow);
}
.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap);
  padding-block: 0.875rem;
}
.masthead .eyebrow { color: var(--yellow); }

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  margin-inline-start: auto;
}
.nav__link {
  font-family: var(--cond);
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--white);
  padding-block: 0.25rem;
  border-bottom: 3px solid transparent;
}
.nav__link:hover { color: var(--yellow); }
.nav__link.is-active {
  color: var(--white);
  border-bottom-color: var(--yellow);
}

/* «Logg ut» (decision 22). Set like a nav link rather than a .btn: a black-bordered button beside
   five uppercase links would read as the page's primary action, and logging out never is. A form,
   because it is a write — there is no client-side JavaScript to make a link do it. */
.masthead__logout { margin: 0; }
.logout {
  font-family: var(--cond);
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--yellow);
  background: transparent;
  border: 0;
  border-bottom: 3px solid transparent;
  padding: 0.25rem 0;
  cursor: pointer;
}
.logout:hover { color: var(--white); border-bottom-color: var(--yellow); }

/* --- Sections, grid, cards ------------------------------------------------------------------ */
.section { margin-block-end: var(--gap-lg); }
/* The last section's margin would stack on main's own bottom padding: ~76px of ground before the
   footer band, which read as an empty block. Only when it really is the last thing in main. */
.section:last-child { margin-block-end: 0; }
.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-block-end: 0.75rem;
}
.section__head .h2 { color: var(--white); }
.section__head .eyebrow { color: var(--yellow); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: var(--gap);
}

.card {
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.125rem 1.25rem;
}
.card__title {
  font-family: var(--cond);
  font-weight: 700;
  font-size: 1.375rem;
  line-height: 1.15;
  text-transform: uppercase;
  margin: 0.25rem 0 0.5rem;
}
.card__title a { text-decoration: none; color: inherit; }
.card__title a:hover { text-decoration: underline; }
/* Black, not grey: the match name and the qualifier are the two facts the card exists to carry,
   and label grey on a card the size of a phone reads as decoration. */
.card__meta {
  color: var(--black);
  font-size: 0.9375rem;
  margin: 0 0 0.5rem;
}

/* A sale window. Column flex so the actions can be pushed to the bottom edge of the card and
   every card in a row ends on the same line. */
.card--window {
  display: flex;
  flex-direction: column;
}
.card__qualifier { margin-block-end: 0.375rem; }
.card__fixture { margin-block-end: 0.625rem; }
/* Our state in words on the left, LFC's status chip on the right. It wraps rather than squeezes:
   «Åpent nå — stenger om 3 t 20 min» beside «Sjekk tilgjengelighet» is too long for 360px. */
.card__state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.375rem 0.75rem;
  font-weight: 600;
  color: var(--black);
  margin: 0 0 0.875rem;
}
.card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
  margin-top: auto;
}

/* Open now. Same 6px left rule the health strip uses for "look here", in green rather than
   yellow — yellow is the accent, green is the state. */
.card--open { border-left: 6px solid var(--green); }
.card--open .card__state { color: var(--green); }

/* A white block that is not a card: the empty state, the health strip, a plain panel. */
.panel {
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.125rem 1.25rem;
}
.empty {
  background: var(--white);
  border: 1px dashed var(--grey-300);
  border-radius: var(--radius);
  color: var(--grey-600);
  padding: 1.25rem;
  margin: 0;
}

/* --- Health strip --------------------------------------------------------------------------- */
.health-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 2rem;
  list-style: none;
  margin: 0 0 var(--gap-lg);
  padding: 0.875rem 1.25rem;
  background: var(--white);
  border-left: 6px solid var(--yellow);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.health-strip__item { min-width: 8rem; }
.health-strip__item strong { display: block; font-weight: 600; }

/* --- Status line -------------------------------------------------------------------------- */
/* One sentence closed, the whole health strip open. A <details> and nothing else — decision 13.
   The tone lives on the parent: it colours both the left rule and the dot, so the state is
   readable at a glance and again in words. */
.status {
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-left: 6px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin: 0.875rem 0 var(--gap-lg);
}
.status--ok { border-left-color: var(--green); }
.status--stale { border-left-color: var(--yellow); }
.status--failed { border-left-color: var(--red); }
.status--none { border-left-color: var(--grey-300); }

.status__summary {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 44px;
  padding: 0.5rem 1rem;
  cursor: pointer;
  list-style: none;
}
/* The default triangle is replaced by the chevron on .status__toggle. */
.status__summary::-webkit-details-marker { display: none; }

.status__dot {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--grey-300);
}
.status--ok .status__dot { background: var(--green); }
.status--stale .status__dot { background: var(--yellow); }
.status--failed .status__dot { background: var(--red); }
.status--none .status__dot { background: var(--grey-300); }

.status__text {
  flex: 1;
  min-width: 0;
  line-height: 1.35;
}

.status__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  flex: none;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--grey-600);
  white-space: nowrap;
}
.status__toggle::after {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  margin-block-start: -0.25rem;
  border-right: 2px solid var(--grey-600);
  border-bottom: 2px solid var(--grey-600);
  transform: rotate(45deg);
}
.status[open] .status__toggle::after {
  margin-block-start: 0.125rem;
  transform: rotate(-135deg);
}
/* The healthy sentence in two lengths. Measured at 360px: 194px remain beside «Detaljer», the
   long form needs 255, the short one 170. The narrow breakpoint swaps them. */
.status__short { display: none; }

/* Open, the strip is the body of the panel rather than a panel of its own. Its own rule is left
   alone — /kilder and /kamper still render it standalone. */
.status .health-strip {
  margin: 0;
  border-left: 0;
  border-radius: 0;
  border-top: 1px solid var(--grey-300);
  box-shadow: none;
}

/* --- Pills and badges ------------------------------------------------------------------------
   A pill is a standing label (DRY_RUN, a sale status). A badge is a row's state. */
.pill,
.badge {
  display: inline-block;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.3125rem 0.5625rem;
  border-radius: var(--radius);
  white-space: nowrap;
}
.pill { background: var(--grey-100); color: var(--black); border: 1px solid var(--grey-300); }
.pill--yellow { background: var(--yellow); border-color: var(--yellow); color: var(--black); }
.pill--black { background: var(--black); border-color: var(--black); color: var(--white); }

/* Flat, every one of them: a state is a fact about a row, and an outlined box in the state column
   is exactly what a button looks like here (.btn is white with a black border). The transparent
   border keeps the height of the pills and tags beside them. Three weights: filled black for what
   was sent, a grey wash for what was recorded, and bare text for what was deliberately not news. */
.badge { border: 1px solid transparent; background: var(--grey-100); color: var(--grey-700); cursor: default; }
.badge--notify { background: var(--black); color: var(--white); }
.badge--silent { background: var(--grey-100); color: var(--grey-700); }
.badge--suppressed { background: transparent; color: var(--grey-600); padding-inline: 0; }
.badge--ok { background: var(--grey-100); color: var(--black); }
.badge--degraded { background: var(--yellow); color: var(--black); }
.badge--failed { background: var(--red); color: var(--white); }
.badge--off { background: var(--grey-300); color: var(--black); }

/* --- Tags ------------------------------------------------------------------------------------
   The third small label, and the only one that is a *kind* rather than a state: what happened to
   a row in the changes feed. Narrower and tighter than a badge, and set to one common min-width
   so a column of them lines up. The transparent border keeps the outlined variants the same
   height as the filled ones. */
.tag {
  display: inline-block;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.3125rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  white-space: nowrap;
  /* Wide enough for «Fjernet», the longest label, so the title column starts at the same x in
     every row of a mixed batch. */
  min-width: 4rem;
  text-align: center;
}
.tag--new { background: var(--black); color: var(--white); }
.tag--opened { background: var(--green); color: var(--white); }
/* Yellow, not outlined: white with a black border was .btn in miniature. */
.tag--changed { background: var(--yellow); color: var(--black); }
.tag--closed,
.tag--removed { background: var(--grey-300); color: var(--black); }
.tag--failed { background: var(--red); color: var(--white); }
.tag--other { background: var(--grey-100); color: var(--grey-700); }

/* --- LFC's status ----------------------------------------------------------------------------
   The club's own word for a window — translated where the route knows it, raw where it does not,
   and the raw string in the title either way. Always flat and never in the actions row: a status
   is a fact about the window, and a fact must not look like something to press. Green for open,
   grey for over, a yellow wash for coming, plain for anything else. */
.lfc-status {
  display: inline-block;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.3125rem 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  white-space: nowrap;
  cursor: default;
  background: var(--grey-100);
  color: var(--black);
}
.lfc-status--open { background: var(--tint-green); color: var(--green-deep); }
.lfc-status--ended { background: var(--grey-100); color: var(--grey-700); }
.lfc-status--soon { background: var(--tint-yellow); color: var(--black); }

/* --- Buttons -------------------------------------------------------------------------------- */
.btn {
  display: inline-block;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
  padding: 0.5rem 1rem;
  border: 2px solid var(--black);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--black);
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--grey-100); color: var(--black); }
.btn--primary { background: var(--black); color: var(--white); }
.btn--primary:hover { background: var(--red-deep); border-color: var(--red-deep); color: var(--white); }
.btn--ghost { background: transparent; border-color: var(--grey-600); color: var(--grey-600); }
.btn--ghost:hover { border-color: var(--black); color: var(--black); background: transparent; }
.btn--danger { background: var(--white); border-color: var(--red); color: var(--red-deep); }
.btn--danger:hover { background: var(--red); color: var(--white); }

/* A row of one-button forms: the four «Kjør nå» buttons on /kilder, and the on/off and delete
   forms inside a table cell on /regler. Every action is its own <form> (decision 13, no client
   JavaScript), and a form is a block — this is what puts them on one line. */
.actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.actions form { margin: 0; }
/* The one action on the front page worth a thumb: yellow, 44px tall, and full width on a phone. */
.btn--cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  background: var(--yellow);
  border-color: var(--black);
  color: var(--black);
}
.btn--cta:hover { background: var(--black); color: var(--yellow); }

/* --- Tables --------------------------------------------------------------------------------- */
.table-scroll { overflow-x: auto; }
.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.table th,
.table td {
  text-align: left;
  padding: 0.625rem 0.875rem;
  border-bottom: 1px solid var(--grey-300);
  vertical-align: top;
}
.table th {
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--grey-600);
  background: var(--grey-100);
  white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--grey-100); }

/* --- Changes feed ----------------------------------------------------------------------------
   What used to be a four-column table. One white panel, batches inside it, and a three-column
   grid per row: tag, body, state. The body column is minmax(0, 1fr) so a long sale title
   shortens the column instead of pushing the state column off the screen. */
.feed {
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.feed__batch { padding: 1rem 1.25rem; }
.feed__batch + .feed__batch { border-top: 1px solid var(--grey-300); }

/* The batch's timestamp, and — when every row under it shares one — its tag and its state, said
   once here instead of once per row. */
.feed__when {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grey-600);
  margin: 0 0 0.5rem;
}
/* No tag column when the header carries the tag: the rows are title and state only. */
.feed__batch--untagged .feed__item { grid-template-columns: minmax(0, 1fr) auto; }
/* A window that is over: still a row, still a link, but not the one to read first. Regular weight
   in the reading grey rather than opacity — 60% black on white would drop the qualifier under AA. */
.feed__item--ended .feed__title { color: var(--grey-700); font-weight: 400; }
.feed__item--ended .feed__title:hover { color: var(--black); }
/* The one line about what the page is not showing, and the link that shows it. */
.feed__note {
  margin: 0;
  padding: 0.75rem 1.25rem;
  border-top: 1px solid var(--grey-300);
  font-size: 0.9375rem;
  color: var(--grey-700);
}

.feed__bucket { margin-block-start: 0.75rem; }
.feed__bucket:first-of-type { margin-block-start: 0; }
/* An h4 (batch time is the h3 above it), reset so only the match name is bold. */
.feed__bucket-head { margin: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; }
.feed__bucket-head strong { font-size: 1rem; font-weight: 600; color: var(--black); }
.feed__sub { font-size: 0.875rem; color: var(--grey-600); }

.feed__items {
  list-style: none;
  margin: 0;
  padding: 0;
}
.feed__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  column-gap: 0.75rem;
  align-items: start;
  padding: 0.625rem 0;
}
.feed__item + .feed__item { border-top: 1px solid var(--grey-300); }
.feed__body { min-width: 0; }
.feed__state {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  justify-content: flex-end;
  white-space: normal;
}

/* Still a link, but black: on a white panel the red-deep link colour next to black body text
   read as an error. The grey underline carries the affordance instead of the colour. */
.feed__title {
  color: var(--black);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--grey-300);
  text-underline-offset: 3px;
  overflow-wrap: anywhere;
}
.feed__title:hover {
  color: var(--black);
  text-decoration-color: var(--red-deep);
}
.feed__qualifier {
  display: block;
  font-size: 0.9375rem;
  color: var(--grey-700);
  overflow-wrap: anywhere;
}

/* --- Diff ----------------------------------------------------------------------------------- */
.diff {
  font-family: var(--mono);
  font-size: 0.875rem;
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  padding: 0.5rem;
  margin: 0 0 var(--gap);
  overflow-x: auto;
}
.diff__del,
.diff__add {
  display: block;
  padding: 0.1875rem 0.5rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.diff__del { background: var(--tint-red); color: var(--red-deep); }
.diff__add { background: var(--tint-yellow); color: var(--black); }
.diff__del::before { content: '- '; font-weight: 700; }
.diff__add::before { content: '+ '; font-weight: 700; }

pre {
  font-family: var(--mono);
  font-size: 0.8125rem;
  background: var(--grey-100);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  padding: 0.75rem;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- Flash and forms ------------------------------------------------------------------------ */
.flash {
  background: var(--yellow);
  border-radius: var(--radius);
  color: var(--black);
  font-weight: 600;
  margin: 0 0 var(--gap-lg);
  padding: 0.75rem 1rem;
}

.form {
  background: var(--white);
  border: 1px solid var(--grey-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.125rem 1.25rem;
}
.form__row { display: block; margin-block-end: 0.875rem; }
.form__row:last-of-type { margin-block-end: var(--gap); }
.form__row > .eyebrow { display: block; margin-block-end: 0.25rem; }
.form fieldset { border: 1px solid var(--grey-300); border-radius: var(--radius); padding: 0.75rem; margin: 0 0 0.875rem; }
.form legend { padding-inline: 0.375rem; }
.form__line { display: block; padding: 0.1875rem 0; overflow-wrap: anywhere; }
.form input[type='text'],
.form input[type='password'],
.form input[type='number'],
.form select {
  font: inherit;
  width: 100%;
  max-width: 34rem;
  padding: 0.4375rem 0.5rem;
  border: 1px solid var(--grey-600);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--black);
}
.form__error {
  background: var(--tint-red);
  border-left: 4px solid var(--red);
  color: var(--red-deep);
  font-weight: 600;
  margin: 0 0 var(--gap);
  padding: 0.625rem 0.875rem;
}

/* --- Login -----------------------------------------------------------------------------------
   One white card on the red ground and nothing else (decision 21). It is the .form card, narrowed
   and centred: that keeps the inputs, the error banner and the button identical to every other form
   in the UI, and adds exactly one class to the frozen contract. body.bare paints its text white for
   the hand-written 503/403 pages, so the card has to paint its own back to black. */
.login {
  max-width: 26rem;
  margin-inline: auto;
  color: var(--black);
}
.login .h1 {
  color: var(--black);
  font-size: 2rem;
  margin-block-end: 0.875rem;
}
/* Full width and thumb-sized: this is the one button on the page, and on a phone it is the only
   thing to press. */
.login .btn {
  width: 100%;
  min-height: 44px;
}
.login input { min-height: 44px; }
.login .muted { margin: 1rem 0 0; font-size: 0.875rem; }

/* --- Filter chips and pagination (used by /endringer) --------------------------------------- */
.chips { display: flex; flex-wrap: wrap; gap: 0.375rem; list-style: none; margin: 0 0 0.75rem; padding: 0; }
.chip {
  display: inline-block;
  font-family: var(--cond);
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.3125rem 0.625rem;
  border: 1px solid var(--white);
  border-radius: var(--radius);
  background: transparent;
  color: var(--white);
}
.chip:hover { background: var(--red-deep); color: var(--white); }
.chip--on { background: var(--yellow); border-color: var(--yellow); color: var(--black); }
.chip--on:hover { background: var(--yellow); color: var(--black); }
/* «Se alle» in a section head: a link on the red ground, and the outlined white chip was too
   easy to lose there. Yellow like the call to action, because that is what it is — black on
   yellow 15.4:1, the yellow itself 4.77:1 against the red. The /endringer filter chips keep the
   outline: there, yellow means «on». */
.section__head .chip { background: var(--yellow); border-color: var(--yellow); color: var(--black); }
.section__head .chip:hover { background: var(--black); border-color: var(--black); color: var(--yellow); }

.pager {
  display: flex;
  align-items: center;
  gap: var(--gap);
  margin-block-start: var(--gap);
  color: var(--white);
}
.pager a { color: var(--white); }

/* --- Foot ----------------------------------------------------------------------------------- */
.foot {
  background: var(--red-deep);
  border-top: 4px solid var(--yellow);
  color: var(--white);
  padding-block: 1rem;
}
.foot .muted { color: var(--white); opacity: 0.85; }
.foot a { color: var(--yellow); }

/* --- Narrow ----------------------------------------------------------------------------------
   One breakpoint for the whole app. Two rules govern everything below: nothing a thumb can hit is
   under 44px, and no column may be narrower than the longest word it has to hold. Where a 44px
   target would blow up the vertical rhythm, the padding is paid back with a negative margin. */
@media (max-width: 720px) {
  .page { padding-inline: 1rem; }
  .grid { grid-template-columns: 1fr; }
  .health-strip { flex-direction: column; gap: 0.5rem; }
  .section__head { flex-direction: column; align-items: flex-start; }
  .h1 { font-size: 2rem; }

  /* Masthead: eyebrow and the DRY_RUN pill share the first line, the nav gets the second one to
     itself. Stacked in a column the five links took ~260px of a 640px-tall screen. */
  .masthead__inner {
    flex-flow: row wrap;
    align-items: center;
    gap: 0.25rem 0.75rem;
    padding-block: 0.375rem;
  }
  /* The DRY_RUN pill keeps the right edge and «Logg ut» sits just inside it. With no pill — prod,
     DRY_RUN off — the logout form takes the auto margin over; the `~` rule is the more specific of
     the two, so the order of these three lines does not matter. */
  .masthead__inner > .pill { margin-inline-start: auto; }
  .masthead__inner > .masthead__logout { margin-inline-start: auto; }
  .masthead__inner > .pill ~ .masthead__logout { margin-inline-start: 0; }
  .logout {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    padding-block: 0;
  }
  .nav {
    order: 1;
    flex-basis: 100%;
    margin-inline-start: 0;
    gap: 0 0.875rem;
  }
  .nav__link {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    padding-block: 0;
  }

  /* «Se alle» and the /health link are links inside a line of prose; give them a box. */
  .section__head .chip {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
  }
  .foot a { display: inline-block; padding-block: 0.625rem; }

  .status__summary { padding: 0.375rem 0.875rem; }
  .status__text { font-size: 0.9375rem; line-height: 1.3; }

  .card__actions .btn--cta { width: 100%; }

  /* Feed rows lose the third column: the state chips drop under the body, still in column 2 so
     they stay aligned with the title rather than with the tag. */
  .feed__batch { padding: 0.875rem 1rem; }
  .feed__item { grid-template-columns: auto minmax(0, 1fr); }
  .feed__state {
    grid-column: 2;
    justify-content: flex-start;
    margin-block-start: 0.375rem;
  }
  .feed__title {
    display: inline-block;
    padding-block: 0.625rem;
    margin-block: -0.4375rem;
  }
  /* Without a tag column the row is one column, and the state sits under the title in it. */
  .feed__batch--untagged .feed__item { grid-template-columns: minmax(0, 1fr); }
  .feed__batch--untagged .feed__state { grid-column: 1; }
  .feed__note { padding: 0.75rem 1rem; }
  /* «Vis dem» / «Skjul dem» inside a line of prose: a 44px box, paid back with a negative margin. */
  .feed__note a,
  .empty a {
    display: inline-block;
    padding-block: 0.625rem;
    margin-block: -0.625rem;
  }

  /* The status sentence in its short form: «Fersk · 4 min siden · alle ok» fits beside «Detaljer»
     at 360px, the long form does not. */
  .status__long { display: none; }
  .status__short { display: inline; }

  /* Fixtures stop being a table and become one card per row: the fourth column was clipped off
     the right edge and the first wrapped to one word per line. */
  .table--cards,
  .table--cards tbody { display: block; }
  .table--cards thead { display: none; }
  .table--cards tbody tr {
    display: block;
    padding: 0.75rem 0.875rem;
    border-bottom: 1px solid var(--grey-300);
  }
  .table--cards tbody tr:last-child { border-bottom: 0; }
  .table--cards tbody tr:hover { background: transparent; }
  .table--cards td {
    display: block;
    padding: 0;
    border-bottom: 0;
  }
  .table--cards .cell--primary {
    font-weight: 600;
    font-size: 1.0625rem;
    color: var(--black);
  }
  .table--cards .cell--meta {
    display: inline;
    font-size: 0.9375rem;
    color: var(--grey-700);
  }
  .table--cards .cell--meta + .cell--meta::before { content: ' · '; }
  /* The fixture status is a desktop nicety; on a phone it is the column that got clipped. */
  .table--cards .cell--aside { display: none; }
}
