/* Archetype 1 — design-forward portfolio and marketing.
 *
 * Tenant branding arrives as custom properties from TenantTheme.css_variables(),
 * set on :root by the base template. Everything else is fixed: a tenant
 * chooses content and an accent, not a layout.
 *
 * No webfont. A system stack satisfies plan section 4.2's ban on loading
 * fonts from third parties, loads instantly, and leaves a real typeface as a
 * later decision needing actual font files.
 */

:root {
  --accent: #1f4e5f;
  --accent-foreground: #ffffff;

  --ink: #16181d;
  --ink-muted: #52575f;
  --page: #ffffff;
  --panel: #f4f2ee;
  --rule: #dcd8d1;

  --measure: 38rem;
  --page-max: 76rem;

  --step-0: 1.0625rem;
  --step-1: 1.3rem;
  --step-2: 1.75rem;
  --step-3: 2.4rem;
  --step-4: clamp(2.6rem, 6vw, 4.2rem);

  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.75rem;
  --space-4: 3rem;
  --space-5: 5rem;

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
}

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

/* The footer sits at the bottom of the window on a short page (a sign-in,
   the Ground Control no-access page) rather than half way up (Ian, 13 Oct):
   the page is a column and the main content takes the spare height. */
body {
  /* The narrowest phones in use are about 320px wide: below that the page
     scrolls sideways rather than squeezing text into a sliver (Ian, 29 Oct). */
  min-width: 20rem;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

h1,
h2,
h3 {
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }

p,
ul,
ol {
  margin: 0 0 var(--space-2);
  max-width: var(--measure);
}

a {
  color: var(--accent);
  text-underline-offset: 0.15em;
}

a:hover { text-decoration-thickness: 2px; }

img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Visible focus everywhere. Removing outlines without replacing them is the
 * most common keyboard-accessibility failure on a styled site. */
:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  background: var(--accent);
  color: var(--accent-foreground);
  padding: var(--space-2);
  z-index: 10;
}

.skip-link:focus {
  left: var(--space-2);
  top: var(--space-2);
}

.shell {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-3);
}

/* Header */

.site-header {
  border-bottom: 1px solid var(--rule);
  padding-block: var(--space-2);
}

.site-header .shell {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  align-items: center;
  justify-content: space-between;
}

.site-id {
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}

/* Logos vary enormously: a square device reads fine at 48px tall, a wide
 * lockup with two lines of text does not. Constrain width as well as height
 * so both shapes get a sensible size. */
.site-id img {
  max-height: 4.5rem;
  max-width: 16rem;
  width: auto;
}

/* The logo and strapline take whatever width the navigation leaves, so the
 * strapline stays on one line where there is room and wraps beside the
 * navigation where there isn't. The navigation drops below only when the
 * brand would be narrower than its flex basis, as on a phone. */
.site-brand {
  flex: 1 1 18rem;
  min-width: 0;
}

.site-tagline {
  margin: var(--space-1) 0 0;
  max-width: none;
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--ink-muted);
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
}

.site-nav a {
  color: var(--ink);
  text-decoration: none;
  font-weight: 500;
}

.site-nav a:hover,
.site-nav a[aria-current="page"] {
  color: var(--accent);
  text-decoration: underline;
}

/* Phones (#200, 29 Oct 2026): the header took about a quarter of the first
   screen. A smaller logo and strapline, and less space between the brand
   and the menu; wider screens unchanged. */
@media (max-width: 47.99rem) {
  .site-header .shell {
    row-gap: var(--space-1);
  }

  .site-id img {
    max-height: 3.5rem;
    max-width: 12.5rem;
  }

  .site-tagline {
    font-size: 0.875rem;
  }

  .site-nav ul {
    gap: var(--space-1) var(--space-2);
  }
}

/* Hero */

/* Less space above the title on a phone, where every line of the first
   screen counts, and a little less on wider screens too (#200, Ian, 29 Oct
   2026: was 5rem everywhere). The introduction is body-sized on a phone, so
   a home page's button reaches the first screen. */
.hero {
  padding-block: var(--space-3);
}

.hero__intro {
  font-size: var(--step-0);
  color: var(--ink-muted);
  max-width: var(--measure);
}

@media (min-width: 48rem) {
  .hero {
    padding-block: var(--space-4);
  }

  .hero__intro {
    font-size: var(--step-1);
  }
}

/* A home page's looping animation (14 Oct 2026). Shown whole, never
   cropped: an animation is composed to its frame. The still frame shows
   instead when the visitor's device asks for less motion. */
.hero__media {
  margin-top: var(--space-4);
}

.hero__video,
.hero__still {
  display: block;
  width: 100%;
  height: auto;
  max-height: 80vh;
  object-fit: contain;
}

.hero__still {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero__video {
    display: none;
  }

  .hero__still {
    display: block;
  }
}

.hero__image {
  margin-top: var(--space-4);
  width: 100%;
  max-height: 26rem;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  /* Faces sit high in a portrait photograph, so a centred crop takes the
   * chin and leaves the forehead. */
  object-position: center 30%;
}

/* The image or video beside the text (P49, 20 Oct 2026). On a phone the
 * media comes first, so the page opens on the picture rather than a screen
 * of text, capped so the heading still starts on the first screen. From
 * 48rem it sits beside the text, 60/40 like the panels, the text in the
 * wider column. Shown whole, never cropped: portrait media is the point. */
.hero--beside .shell {
  display: grid;
  gap: var(--space-3);
}

.hero--beside .hero__media,
.hero--beside .hero__image {
  order: -1;
  margin-top: 0;
}

.hero--beside .hero__video,
.hero--beside .hero__still,
.hero--beside .hero__image {
  max-height: 65vh;
  max-height: 65svh;
}

.hero--beside .hero__image {
  height: auto;
  aspect-ratio: auto;
  object-fit: contain;
}

/* The video's own shape, not the column's, so its play bar is as wide as
 * the picture rather than the empty space beside a portrait frame. */
.hero--beside .hero__video,
.hero--beside .hero__still {
  width: auto;
  max-width: 100%;
  margin-inline: auto;
}

@media (min-width: 48rem) {
  .hero--beside .shell {
    grid-template-columns: 3fr 2fr;
    gap: var(--space-4);
    align-items: center;
  }

  .hero--beside .hero__media,
  .hero--beside .hero__image {
    order: 0;
  }

  .hero--beside .hero__video,
  .hero--beside .hero__still,
  .hero--beside .hero__image {
    max-height: 80vh;
  }

  /* Explicit placement, as the panels do, so the text keeps the wider
   * column whichever side the media is on. */
  .hero--media-left .shell {
    grid-template-columns: 2fr 3fr;
  }

  .hero--media-left .hero__media,
  .hero--media-left .hero__image {
    grid-column: 1;
    grid-row: 1;
  }
}

/* Large (Howard, 23 Oct 2026): the image or video as the main thing on the
 * page. On a phone it may fill most of the screen; on a wide screen it takes
 * about two-thirds, beside a narrow column of text on the right. After the
 * beside rules above, which it refines. */
.hero--media-large .hero__video,
.hero--media-large .hero__still,
.hero--media-large .hero__image {
  max-height: 85vh;
  max-height: 85svh;
}

@media (min-width: 48rem) {
  .hero--media-large .shell {
    grid-template-columns: 2fr 1fr;
  }

  .hero--media-large .hero__media,
  .hero--media-large .hero__image {
    grid-column: 1;
    grid-row: 1;
  }

  .hero--media-large .hero__video,
  .hero--media-large .hero__still,
  .hero--media-large .hero__image {
    max-height: 88vh;
  }
}

/* The members' sign-in link (ADR 0013, section 7), where the account menu
 * sits once someone is signed in. */
.member-sign-in {
  font-size: 0.9rem;
  font-weight: 700;
}

/* A hero carrying only a title and subtitle needs less breathing room
 * beneath it than one ending in a full-width image. */
.hero:not(:has(.hero__image)) {
  padding-bottom: var(--space-2);
}

/* Panels. Alternating background, and image beside text on wide screens with
 * the side flipping so the page does not read as a single column of slabs. */

.panel {
  padding-block: var(--space-4);
  border-top: 1px solid var(--rule);
}

@media (min-width: 48rem) {
  .panel {
    padding-block: var(--space-5);
  }
}

.panel:nth-child(even) {
  background: var(--panel);
}

.panel__inner {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

@media (min-width: 48rem) {
  /* Text-led: the illustration supports the paragraph rather than competing
   * with it. An image-led tenant (a portfolio) wants the opposite, which is
   * what a second archetype is for. */
  .panel__inner {
    grid-template-columns: 3fr 2fr;
  }

  /* Explicit column placement rather than `order`, which would move the
   * media into the text's wider column and reverse the 60/40 split. */
  .panel:nth-child(even) .panel__media {
    grid-column: 1;
    grid-row: 1;
  }

  .panel:nth-child(even) .panel__inner {
    grid-template-columns: 2fr 3fr;
  }

  /* A panel with no image keeps the text at a readable measure rather than
   * stretching it across the full width. */
  .panel__inner:not(:has(.panel__media)) {
    grid-template-columns: minmax(0, var(--measure));
  }
}

.panel h2 a {
  color: inherit;
  text-decoration: none;
}

.panel h2 a:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* No fixed ratio: a work's own proportions are part of the work. A services
 * panel tolerates a crop; a painting does not. Capped in height so a tall
 * image cannot set the height of the whole panel. */
.panel__media img {
  max-height: 22rem;
  max-width: 100%;
  width: auto;
  height: auto;
  margin-inline: auto;
}

/* Archetype one is text-led, and its panel illustrations are drawn on white.
 * Multiply lets that white take on the panel colour, so an illustration sits
 * on the cream panels instead of showing as a white card. White panels need
 * no rule: multiplying by white changes nothing. Not for photographs of
 * artworks, whose colours it would tint; image-led tenants get their own
 * archetype (sprint 2 record, lesson 6). */
.panel:nth-child(even) .panel__media img {
  mix-blend-mode: multiply;
}

/* Buttons */

.button {
  display: inline-block;
  background: var(--accent);
  color: var(--accent-foreground);
  padding: 0.75rem var(--space-3);
  font-weight: 600;
  text-decoration: none;
  border: 2px solid transparent;
}

.button:hover {
  background: var(--page);
  color: var(--accent);
  border-color: var(--accent);
  text-decoration: none;
}

/* A second, quieter action beside a main one. */
.button--quiet {
  background: var(--page);
  color: var(--accent);
  border-color: var(--accent);
}

.button--quiet:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}

/* Body content */

.prose {
  padding-block: var(--space-4);
}

.prose blockquote {
  margin: var(--space-3) 0;
  padding-left: var(--space-3);
  border-left: 4px solid var(--accent);
  font-size: var(--step-1);
  color: var(--ink-muted);
}

.prose hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: var(--space-4) 0;
}

/* A hero with no image leaves its own bottom padding and the prose block's
 * top padding stacked on top of each other. */
.hero + .prose {
  padding-top: 0;
}

.prose h2 {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
}

.prose h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Browsers italicise <address> by default. It is a semantic element for
 * contact details, not an instruction to set them in italic. */
.prose address,
.site-footer address {
  font-style: normal;
}

/* Wagtail's rich text image alignments. It emits the class; the project
 * supplies the CSS, or an editor's choice silently does nothing. */
.prose .richtext-image {
  margin-block: var(--space-2);
}

.prose .richtext-image.full-width {
  width: 100%;
}

@media (min-width: 40rem) {
  .prose .richtext-image.left {
    float: left;
    max-width: 30%;
    margin: 0 var(--space-3) var(--space-2) 0;
  }

  .prose .richtext-image.right {
    float: right;
    max-width: 30%;
    margin: 0 0 var(--space-2) var(--space-3);
  }
}

/* A float must not escape its section. */
.prose::after {
  content: "";
  display: table;
  clear: both;
}

/* Footer */

.site-footer {
  margin-top: var(--space-5);
  background: var(--ink);
  color: #e8e6e2;
  padding-block: var(--space-4);
}

.site-footer a { color: #fff; }

.site-footer .shell {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 48rem) {
  .site-footer .shell {
    grid-template-columns: repeat(3, 1fr);
  }
}

.site-footer h2 {
  font-size: var(--step-0);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #a9a49c;
}

.site-footer ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.legal {
  border-top: 1px solid #33363d;
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  color: #a9a49c;
  font-size: 0.9rem;
}

.legal p { max-width: none; }

/* The privacy policy's date sits under its title (F5). */
.privacy-updated {
  color: var(--ink-muted);
}

/* The legal block is one statement, not a row of columns: it spans the
 * footer's full width rather than inheriting the three-column grid above,
 * which squeezed it into the first column on wide screens. */
.site-footer .shell.legal {
  grid-template-columns: 1fr;
  gap: var(--space-1);
}

/* Private preview (ADR 0010): the notice shown while viewing a private
   site, and the branded passphrase page. Neutral on purpose so it sits on
   any tenant's theme; append to static/css/archetype-one.css. */
 
.preview-notice {
  background: #1a1a1f;
  color: #fff;
  font-size: 0.9rem;
}
 
.preview-notice .shell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  padding-block: 0.5rem;
}
 
.preview-notice p {
  margin: 0;
}
 
.preview-notice button {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 4px;
  padding: 0.25rem 0.75rem;
  cursor: pointer;
}
 
.preview-login {
  max-width: 32rem;
  padding-block: 3rem;
}
 
.preview-login form {
  display: grid;
  gap: 0.5rem;
  margin-block: 1.5rem 1rem;
}
 
.preview-login input[type="text"] {
  font: inherit;
  font-size: 1.1rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid currentColor;
  border-radius: 4px;
}
 
/* The passphrase and sign-in buttons wear the site's accent, like every
   other button, with room above them (Ian, 14 and 15 Oct 2026: they were a
   fixed near-black, and sat tight under the box). The accent is checked for
   contrast when it is set, and its text colour chosen to match. */
.preview-login button {
  font: inherit;
  justify-self: start;
  margin-top: 0.75rem;
  padding: 0.6rem 1.25rem;
  border: 2px solid transparent;
  border-radius: 4px;
  background: var(--accent);
  color: var(--accent-foreground);
  cursor: pointer;
}

.preview-login button:hover {
  background: var(--page);
  color: var(--accent);
  border-color: var(--accent);
}
 
.preview-error {
  border-left: 4px solid #b3261e;
  padding-left: 0.75rem;
}
 
.preview-hint {
  font-size: 0.9rem;
  opacity: 0.8;
}
/* Text for screen readers only, such as "Account menu for" before a name. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The account menu (ADR 0013): the signed-in person's name in bold, under
   the navigation at the header's bottom right (Ian, 7 Oct), opening a small
   panel. The navigation and the menu share the header's right-hand column,
   so the header is no taller than the brand beside it. Neutral, like the
   preview notice, so it sits on any tenant's theme. */
.site-header__end {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
}

.account-menu {
  position: relative;
  font-size: 0.9rem;
}

.account-menu summary {
  cursor: pointer;
  list-style: none;
  font-weight: 700;
  color: var(--ink);
  padding: 0.15rem 0.25rem;
  border-radius: 4px;
}

/* No disclosure triangle: the name alone opens the menu (Ian, 7 Oct). */
.account-menu summary::-webkit-details-marker {
  display: none;
}

.account-menu summary:hover,
.account-menu[open] summary {
  color: var(--accent);
}

.account-menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  z-index: 10;
  min-width: 11rem;
  background: var(--page);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.12);
  padding: 0.35rem 0;
}

.account-menu__panel ul {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
}

.account-menu__panel a,
.account-menu__panel button {
  display: block;
  width: 100%;
  padding: 0.45rem 1rem;
  font: inherit;
  font-weight: 400;
  text-align: left;
  color: inherit;
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
}

.account-menu__panel a:hover,
.account-menu__panel button:hover {
  background: var(--panel);
}

/* On a phone the navigation drops below the brand and keeps to the left;
   the name stays on the right. */
@media (max-width: 48rem) {
  .site-header__end {
    align-items: stretch;
  }

  .account-menu {
    align-self: flex-end;
  }
}

/* The sign-in page: the same look as the preview page, with room between
   each label-and-box pair and before the button. */
.sign-in form {
  gap: 1.25rem;
}

.sign-in .field {
  display: grid;
  gap: 0.4rem;
}

.sign-in input[type="text"],
.sign-in input[type="password"] {
  font: inherit;
  font-size: 1.1rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid currentColor;
  border-radius: 4px;
}

.sign-in button {
  margin-top: 0.25rem;
}

/* What signing in records, under the form (F5). */
.sign-in-privacy {
  margin-top: var(--space-3);
  color: var(--ink-muted);
  font-size: 0.95rem;
}

/* Chrome shows saved usernames and passwords in its own small font until
   the visitor first interacts with the page; this keeps ours (Ian, 7 Oct). */
.sign-in input:-webkit-autofill::first-line {
  font-family: var(--font);
  font-size: 1.1rem;
}

/* Two-step sign-in (ADR 0013): the set-up QR code, the key to type by hand
   and the recovery codes. */
/* Drawn at its own size: segno's inline SVG has no viewBox to scale by. */
.two-step-qr svg {
  display: block;
  margin-block: 1rem;
  background: #fff;
  border: 1px solid var(--rule);
  border-radius: 6px;
}

.two-step-secret {
  font-size: 1rem;
  letter-spacing: 0.05em;
  word-break: break-all;
}

.recovery-codes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 1.5rem;
  padding: 1rem 1.25rem;
  list-style: none;
  background: var(--panel);
  border-radius: 6px;
  max-width: none;
}

.recovery-codes code {
  font-size: 1.05rem;
  letter-spacing: 0.05em;
}

/* "Can't scan the QR code?": the setup key stays folded away unless needed,
   so it is not mistaken for a recovery code (Ian, 7 Oct). */
.two-step-manual summary {
  cursor: pointer;
  font-size: 0.95rem;
}

/* Ground Control (ADR 0013, section 5): a site's management information,
   for its admins. Plain and readable on any tenant's theme. */
.ground-control h2 {
  margin-top: var(--space-3);
}

.gc-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0;
  max-width: none;
}

.gc-summary div {
  padding: var(--space-2);
  background: var(--panel);
  border-radius: 6px;
}

.gc-summary dt {
  font-size: 0.9rem;
  color: var(--ink-muted);
}

.gc-summary dd {
  margin: 0.25rem 0 0;
  font-size: var(--step-2);
  font-weight: 700;
}

/* A secondary line in a table cell, such as a campaign link's address (P2). */
.gc-muted {
  color: var(--ink-muted);
  font-size: 0.9rem;
}

/* The table scrolls sideways on a phone rather than squashing its columns. */
.gc-table-wrap {
  overflow-x: auto;
}

.gc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}

.gc-table caption {
  text-align: left;
  padding-bottom: var(--space-1);
  color: var(--ink-muted);
}

.gc-table th,
.gc-table td {
  text-align: left;
  padding: 0.5rem 0.75rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

/* Failed attempts stand out in bold red. Not colour alone: the "What
   happened" column says what failed in words. A fixed red rather than the
   theme's accent, which is the colour of links (Ian, 9 Oct). 6:1 on white. */
.gc-failed td {
  font-weight: 700;
  color: #b42318;
}

/* Something Ground Control itself can't vouch for: results it couldn't
   read, or a source that has gone quiet (ADR 0012, section 6). Said in
   words, in the same fixed red as a failed row, never as an empty table. */
.gc-problem {
  border-left: 4px solid #b42318;
  padding-left: 0.75rem;
  color: #b42318;
  font-weight: 700;
}

/* The status box (P36): a coloured edge by state, never colour alone, since
   the plain words say it. Fixed colours rather than the theme's accent;
   the text stays the page's own ink. */
.gc-status {
  margin: var(--space-3) 0 0;
  padding: var(--space-2);
  background: var(--panel);
  border-left: 6px solid var(--ink-muted);
  border-radius: 6px;
}

.gc-status p {
  margin: 0;
}

.gc-status__message {
  font-weight: 700;
}

.gc-status__line {
  margin-top: 0.25rem;
  font-style: italic;
  color: var(--ink-muted);
}

.gc-status__note {
  font-size: 0.9rem;
  color: var(--ink-muted);
}

.gc-status--ok {
  border-left-color: #1a7f37;
}

.gc-status--amber {
  border-left-color: #b76e00;
}

.gc-status--red {
  border-left-color: #b42318;
}

/* Tabs: one link per panel, each its own page (Ian, 9 Oct). The current
   tab is marked by aria-current, shown bold with an underline bar. */
.gc-tabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--rule);
  max-width: none;
}

.gc-tabs a {
  display: block;
  padding: 0.6rem 0;
  margin-bottom: -1px;
  border-bottom: 3px solid transparent;
  color: var(--ink-muted);
  text-decoration: none;
}

.gc-tabs a:hover {
  color: var(--ink);
}

.gc-tabs a[aria-current="page"] {
  color: var(--ink);
  font-weight: 700;
  border-bottom-color: var(--accent);
}

.ground-control h3 {
  margin-top: var(--space-3);
  font-size: var(--step-1);
}

.gc-daily {
  margin-top: var(--space-3);
}

.gc-daily summary {
  cursor: pointer;
}

/* A native bar for each day, so the daily table reads at a glance without
   JavaScript or inline styles (the CSP allows neither). */
.gc-table meter {
  width: 10rem;
}

/* Ground Control is a working page with full-width tables, so its text
   runs wider than the site's reading width (Ian, 9 Oct): about 110
   characters a line at full screen, still comfortable to read. */
.ground-control p {
  max-width: 60rem;
}

.gc-note {
  color: var(--ink-muted);
  font-size: 0.95rem;
}

/* The page fills the window, header and footer keeping their own height. */
#main {
  flex: 1 0 auto;
}

/* What just happened, after signing someone out: shown once, not muted. */
.gc-status {
  font-weight: 700;
}

/* "Signed in now": the button and its help sit under the Who column, not
   the tick boxes (Ian, 13 Oct). */
.gc-now-actions td {
  padding-top: var(--space-2);
}

.gc-help summary {
  cursor: pointer;
  margin-top: var(--space-2);
}

.gc-help ul {
  margin: 0.5rem 0;
}

/* Team sign-ins, one folding section per day (Ian, 9 Oct). */
.gc-day {
  border-bottom: 1px solid var(--rule);
}

/* The summary keeps its default display, so browsers still draw the
   open-and-close triangle. */
.gc-day summary {
  padding: 0.75rem 0;
  cursor: pointer;
}

.gc-day__date {
  font-weight: 700;
  margin-right: 1rem;
}

.gc-day__summary {
  color: var(--ink-muted);
}

.gc-day .gc-table-wrap {
  margin-bottom: var(--space-2);
}

/* Each day is its own table, and a browser sizes a table's columns from
   its own contents, so days with different text did not line up (Ian,
   9 Oct). A fixed layout takes the widths from the columns below instead,
   the same for every day. The last column takes what is left. Long text
   wraps inside its column rather than spilling into the next; on a phone
   the table keeps its minimum width and scrolls sideways. */
.gc-table--by-day {
  table-layout: fixed;
  min-width: 48rem;
}

.gc-table--by-day th,
.gc-table--by-day td {
  white-space: normal;
  overflow-wrap: anywhere;
}

.gc-col-time {
  width: 5rem;
}

.gc-col-who {
  width: 20%;
}

.gc-col-what {
  width: 22%;
}

.gc-col-device {
  width: 24%;
}

/* The contact form (P11): the sign-in page's look, the full width of the
   reading column, and the site's accent on the button. */
.contact-form {
  max-width: 40rem;
  padding-block: var(--space-3) var(--space-4);
}

.contact-form form {
  display: grid;
  gap: 1.25rem;
  margin-block: 1rem;
}

.contact-form .field {
  display: grid;
  gap: 0.4rem;
}

.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
  font: inherit;
  font-size: 1.1rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid currentColor;
  border-radius: 4px;
}

.contact-form textarea {
  resize: vertical;
}

.contact-form button {
  font: inherit;
  justify-self: start;
  padding: 0.6rem 1.25rem;
  border: 2px solid transparent;
  border-radius: 4px;
  background: var(--accent);
  color: var(--accent-foreground);
  cursor: pointer;
}

.contact-form button:hover {
  background: var(--page);
  color: var(--accent);
  border-color: var(--accent);
}

.field__error {
  margin: 0;
  color: #b3261e;
  font-weight: 600;
}

/* The honeypot: off the page for people, so only something filling in
   every field it finds will fill it in. Not display: none, which some bots
   check for. */
.contact-form__extra {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-form__sent {
  border-left: 4px solid #1a7f37;
  padding-left: 0.75rem;
}

.contact-form__privacy {
  color: var(--ink-muted);
  font-size: 0.95rem;
}

/* The contact page with its form (Ian, 29 Oct 2026): where there is room,
   the text and the form side by side, so the form is seen without
   scrolling; on narrower screens one column, with a link under the title
   that jumps down to the form. */
.contact-jump a {
  font-weight: 600;
}

.hero + .contact-body > .prose {
  padding-top: 0;
}

/* Where the form comes below the text, the text's own bottom padding and
   the form's top padding stacked into a gap of about 90px (Ian, 29 Oct):
   the form's padding alone separates them. */
.contact-body--with-form > .prose {
  padding-bottom: 0;
}

@media (min-width: 64rem) {
  .contact-body--with-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--space-5);
    align-items: start;
  }

  .contact-body--with-form .contact-form {
    padding-top: 0;
  }

  .contact-jump {
    display: none;
  }
}

/* Ground Control's Inbox (P11): the unread count beside the tab's name,
   and new messages in bold. */
.gc-tabs__count {
  display: inline-block;
  min-width: 1.5em;
  margin-left: 0.35rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-foreground);
  font-size: 0.85rem;
  font-weight: 700;
  text-align: center;
}

.gc-inbox__unread td {
  font-weight: 700;
}

.gc-message {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 60rem;
  padding: var(--space-2) var(--space-3);
  border-left: 4px solid var(--rule);
}

.gc-message-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-3);
}

.gc-message-actions form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
}

/* Reply, Mark as junk and Delete: the same size and shape, so they read as
   one row (Ian, 28 Oct). Reply is the main action, in the accent; Mark as
   junk is quieter; Delete is red, as it cannot be undone. */
.gc-message-actions .button,
.gc-message-actions button {
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.25;
  padding: 0.6rem 1.25rem;
  border: 2px solid transparent;
  border-radius: 4px;
  cursor: pointer;
}

.gc-message-actions .gc-button--quiet {
  background: var(--page);
  color: var(--accent);
  border-color: var(--accent);
}

.gc-message-actions .gc-button--danger {
  background: var(--page);
  color: #b42318;
  border-color: #b42318;
}

.gc-message-actions .gc-button--quiet:hover,
.gc-message-actions .gc-button--danger:hover {
  text-decoration: underline;
}

/* Who sent a message and when: a plain list, not the summary tiles, which
   are sized for a single figure and clipped a long email address. */
.gc-details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem var(--space-3);
  margin: var(--space-3) 0;
}

.gc-details div {
  display: contents;
}

.gc-details dt {
  color: var(--ink-muted);
}

.gc-details dd {
  margin: 0;
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* Room between a table or a row of buttons and the note under it. */
.gc-table-wrap + .gc-note,
.gc-empty + .gc-note,
.gc-message-actions + .gc-note {
  margin-top: var(--space-3);
}
