/* Winter Market Vendor Portal — styling.
   Built from Branding/ mockups and the brand guidelines. See branding.md.
   Mobile first: most vendors open this on a phone, often on venue wifi. */

:root {
  /* Brand — Winter Market Brand Guidelines, 2026 */
  --wm-navy:       #0E193E;   /* Midnight Blue */
  --wm-navy-deep:  #12173E;
  --wm-red:        #E31613;   /* Crimson Red */
  --wm-frost:      #BCCCDC;   /* Frosty Grey */
  --wm-slate:      #5A6B92;   /* Slate Blue, darkened for text contrast */
  --wm-slate-line: #6A7BA2;   /* the drawn value, for rules and icons only */
  --wm-snow:       #FFFFFF;   /* Snow White */
  --wm-paper:      #F6F8FA;   /* the dashboard mockup's page ground */
  --wm-ink:        #444342;

  /* Roles — everything below refers only to these */
  --ink:      var(--wm-ink);
  --ink-soft: var(--wm-slate);
  --paper:    var(--wm-paper);
  --card:     var(--wm-snow);
  --accent:   var(--wm-red);
  --line:     #E4E9F0;
  --error:    var(--wm-red);

  --font-display: "IM Fell English", Baskerville, Georgia, serif;
  --font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

/* The browser's own [hidden] rule is a bare attribute selector, so any class
   below that sets `display` beats it and the "hidden" view renders anyway.
   This has to win outright, or two views appear at once. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Shared type -------------------------------------------------------------- */

.display-title,
.display-heading {
  font-family: var(--font-display);
  font-weight: 400;
  /* The guidelines ask for breathing room rather than tight tracking. */
  letter-spacing: 0.01em;
  margin: 0;
}

.eyebrow {
  margin: 0 0 0.9rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--wm-frost);
}

/* The red rule under the eyebrow. Red on navy is 3.66:1 — fine for a rule and
   for display type, never for body text. */
.eyebrow::after {
  content: "";
  display: block;
  width: 3.25rem;
  height: 2px;
  margin-top: 0.7rem;
  background: var(--wm-red);
}

.intro {
  margin: 0 0 1.75rem;
  color: var(--ink-soft);
  font-size: 0.98rem;
}

/* Loading ------------------------------------------------------------------ */

.loading-view {
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: var(--paper);
}

.loading-message {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.95rem;
}

/* ===================== LOGIN ===================== */

.login-layout {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr;
}

.brand-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2rem;
  padding: 2.5rem 1.5rem;
  background-color: var(--wm-navy);
  color: var(--wm-snow);
  overflow: hidden;

  /* The brand icon pattern, from Branding/Winter Market_Background_transparent.png.
     The transparent export is used rather than the flattened one, so the navy
     comes from our own token and the two can never drift apart. Quantised to
     8 colours: 97KB rather than the 7MB original. */
  background-image: url("assets/pattern.png");
  background-repeat: repeat;
  background-size: 480px auto;
}

.display-title {
  font-size: clamp(2.1rem, 8vw, 3.6rem);
  line-height: 1.05;
}

/* "2026" in the mockup is red italic display type. Large enough that 3.66:1
   contrast is acceptable; this must never be applied to small text. */
.display-title em {
  color: var(--wm-red);
  font-style: italic;
}

.tagline {
  margin: 1.1rem 0 0;
  max-width: 27em;
  font-family: var(--font-display);
  font-size: 0.98rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wm-snow);
}

.countdown {
  display: inline-flex;
  margin-top: 2rem;
  border: 1px solid rgba(188, 204, 220, 0.35);
  background: rgba(255, 255, 255, 0.04);
}

.countdown-unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.9rem 1.4rem;
}

.countdown-unit + .countdown-unit {
  border-left: 1px solid rgba(188, 204, 220, 0.25);
}

.countdown-value {
  font-family: var(--font-display);
  font-size: 1.7rem;
  line-height: 1;
  color: var(--wm-snow);
}

.countdown-label {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wm-frost);
}

/* The market-stall illustration. margin-top:auto pushes it to the bottom of
   the panel, just above the footer line, which is where the mockup puts it.
   Shown only once the two-column split exists — see the wider-screens block. */
.brand-illustration {
  display: none;
  width: 100%;
  max-width: 12rem;
  height: auto;
  margin-top: auto;
}

.brand-footer {
  margin: 0;
  font-size: 0.82rem;
  color: var(--wm-frost);
}

/* Sign-in panel ------------------------------------------------------------ */

.form-panel {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2.5rem 1.5rem 3.5rem;
  background: var(--wm-snow);
}

.form-inner {
  width: 100%;
  max-width: 24rem;
}

/* The horizontal logo lockup. The bottom margin is the guidelines' clear space
   rule — at least the height of the globe, which is the full height of this
   image — so the logo is never crowded by the heading under it. */
.logo {
  margin: 0 0 2.25rem;
  text-align: center;
  line-height: 0;
}

.logo img {
  width: 100%;
  /* 16rem keeps the lockup above the guidelines' 120px digital minimum at
     every screen size, without letting it dominate the sign-in form. */
  max-width: 16rem;
  height: auto;
}

.display-heading {
  font-size: clamp(1.6rem, 5vw, 2.1rem);
  color: var(--wm-navy);
  margin-bottom: 0.5rem;
}

/* Form --------------------------------------------------------------------- */

label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wm-navy);
}

input {
  width: 100%;
  /* 1rem keeps iOS Safari from zooming in when the field takes focus. */
  font-size: 1rem;
  font-family: inherit;
  color: var(--ink);
  padding: 0.85rem 0.9rem;
  margin-bottom: 1.25rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: var(--wm-snow);
}

input::placeholder {
  color: #9AA5BC;
}

input:focus-visible {
  outline: 2px solid var(--wm-navy);
  outline-offset: 1px;
}

#code {
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.checkbox {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 1.5rem;
  font-size: 0.88rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  cursor: pointer;
}

.checkbox input {
  width: 1.1rem;
  height: 1.1rem;
  margin: 0;
  flex: none;
  accent-color: var(--wm-red);
}

.button-primary {
  width: 100%;
  /* Comfortably past the 44px minimum tap target. */
  min-height: 3.1rem;
  font-size: 1rem;
  font-family: inherit;
  font-weight: 600;
  color: var(--wm-snow);
  background: var(--wm-red);
  border: none;
  border-radius: 0.4rem;
  cursor: pointer;
}

.button-primary:disabled {
  opacity: 0.65;
  cursor: default;
}

.error {
  margin: 0 0 1.1rem;
  padding: 0.75rem 0.9rem;
  border-radius: 0.4rem;
  background: #FDECEC;
  color: #A8100E;
  font-size: 0.9rem;
}

.help-box {
  margin-top: 1.75rem;
  padding: 1rem 1.1rem;
  background: #F4F7FA;
  border-radius: 0.4rem;
}

.help-title {
  margin: 0 0 0.35rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--wm-navy);
}

.help-body {
  margin: 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* ===================== DASHBOARD ===================== */

/* Measured off Branding/image (6).png, which is drawn at 1210px wide (cropped
   to 1202): 72px gutters, a 1066px content column, and DM Sans for every
   piece of sans text. Colours are sampled from the mockup's own pixels. */

.dashboard {
  max-width: calc(1066px + 2.5rem);
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
  font-family: "DM Sans", var(--font-body);
  color: var(--wm-navy);
}

.dash-header {
  display: flex;
  flex-wrap: wrap;
  /* The date pill sits level with the sub-line, not with the greeting. */
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 35px;
}

.dash-header .display-heading {
  font-size: clamp(1.9rem, 5vw, 39px);
  line-height: 1.2;
  margin: 0;
}

.dash-header .intro {
  margin: 10px 0 0;
  font-size: 16px;
  color: #65718D;
}

.pill {
  margin: 0;
  padding: 0 12px;
  min-height: 31px;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: #EAF0F4;
  color: var(--wm-navy);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.dash-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 23px;
}

/* Both columns end on the same line. The left column's two cards share the
   extra height, which is how the mockup's cards come out 297px and 246px. */
.dash-column {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.dash-column > .card {
  flex: 1 0 auto;
}

.card {
  background: var(--card);
  border: 1px solid #E4E9EE;
  border-radius: 4px;
  /* 25 + the 1px border puts the heading where the mockup draws it. */
  padding: 25px 28px 28px;
}

.card-navy {
  background: var(--wm-navy);
  border-color: var(--wm-navy);
  color: var(--wm-snow);
}

.card-heading {
  margin: 0 0 13px;
  font-size: 13px;
  font-weight: 700;
  line-height: 20px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wm-snow);
}

.card-heading-dark {
  margin-bottom: 19px;
  color: var(--wm-navy);
}

.card-note {
  margin: 0 0 29px;
  font-size: 14px;
  line-height: 18px;
  color: var(--wm-frost);
}

/* Stall details ------------------------------------------------------------ */

/* Floor, zone and stall run across at their natural widths, 32px apart, as
   drawn; size always starts its own row underneath. */
.stat-grid {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 34px 32px;
}

.stat {
  padding-left: 14px;
  border-left: 1px solid rgba(188, 204, 220, 0.4);
}

.stat-wide {
  flex-basis: 100%;
}

/* An organisation's sizes: one table per line. */
.stat dd.stat-lines {
  white-space: pre-line;
}

.stat dt {
  margin: 0 0 6px;
  font-size: 9px;
  font-weight: 600;
  line-height: 1.55;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #B6C3D7;
}

.stat dd {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--wm-snow);
}

/* On a narrow phone three values at full size no longer fit on one row. */
@media (max-width: 30rem) {
  .stat dd {
    font-size: 1.15rem;
  }
}

/* The greeting is focused after sign-in so screen reader users land on the new
   content. That is programmatic focus, not keyboard navigation, so it must not
   paint a focus ring around the heading. */
#greeting:focus {
  outline: none;
}

/* A longer value in one of the narrow columns would otherwise wrap into
   several huge lines and stretch the card. */
.stat dd.stat-long {
  font-size: 1rem;
  line-height: 1.35;
}

/* Documents ---------------------------------------------------------------- */

.document-list {
  display: grid;
  gap: 13px;
}

.document-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 63px;
  padding: 0 16px;
  border: 1px solid #DFE6EE;
  border-radius: 4px;
}

.document-name {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--wm-navy);
}

.document-meta {
  margin: 1px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: #7484A3;
}

/* Red on white is 4.80:1, so this passes as a text link. */
.document-action {
  flex: none;
  min-height: 2.75rem;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--wm-red);
  background: none;
  border: none;
  cursor: pointer;
  white-space: nowrap;
}

.document-action:disabled {
  opacity: 0.6;
  cursor: default;
}

.document-status {
  flex: none;
  padding: 0 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--wm-red);
  white-space: nowrap;
}

/* A note from the sheet ("Free participation") is longer than "Coming soon",
   so it wraps instead of pushing the document name out of the row. */
.document-status-note {
  flex: 0 1 auto;
  max-width: 45%;
  text-align: right;
  white-space: normal;
}

/* Promotional image -------------------------------------------------------- */

/* A fixed 300 x 400 frame on a pale ground, the image fitted inside it, so a
   square or landscape image sits in the same frame as a portrait one. */
.preview,
.image-placeholder {
  width: 100%;
  max-width: 300px;
  aspect-ratio: 3 / 4;
  margin: 22px auto;
  border: 1px solid #DFE6EE;
  border-radius: 2px;
  background: #F6F8FA;
}

.preview img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.button-outline {
  width: 100%;
  min-height: 48px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--wm-navy);
  background: var(--wm-snow);
  border: 1px solid var(--wm-navy);
  border-radius: 3px;
  cursor: pointer;
}

.button-outline:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Shown while the image travels through the backend - about four seconds.
   Sized like the frame it replaces, so the card does not jump when it lands. */
.image-placeholder {
  display: grid;
  place-items: center;
  padding: 1rem;
  text-align: center;
  font-size: 14px;
  color: #7484A3;
}

/* A vendor with no image yet: the same treatment the documents card gives a
   missing invoice, rather than an empty space with no explanation. */
.image-status {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--wm-red);
}

.image-note {
  margin: 0.35rem 0 0;
  font-size: 14px;
  color: #7484A3;
}

/* Banner ------------------------------------------------------------------- */

.banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  min-height: 112px;
  margin-top: 23px;
  padding: 24px 28px;
  border-radius: 4px;
  background: var(--wm-navy);
  color: var(--wm-snow);
}

.banner .banner-heading {
  margin: 0;
  font-size: clamp(1.4rem, 4vw, 26px);
  line-height: 1.2;
  color: var(--wm-snow);
}

.banner-body {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--wm-frost);
}

/* Outlined rather than filled, as drawn. */
.pill-light {
  min-height: 32px;
  padding: 0 13px;
  background: transparent;
  border: 1px solid #6D7B95;
  color: var(--wm-frost);
}

/* Sign out ----------------------------------------------------------------- */

/* Not in the mockup, which is cropped above it, but a vendor on a shared
   device needs a way to leave. Kept quiet, below everything the design shows. */
.dash-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 1.5rem;
}

.button-quiet {
  min-height: 2.75rem;
  padding: 0 1.1rem;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: #65718D;
  background: transparent;
  border: 1px solid #DFE6EE;
  border-radius: 4px;
  cursor: pointer;
}

/* ===================== WIDER SCREENS ===================== */

@media (min-width: 60rem) {
  /* The mockup splits 970/818 — a little over 54% to the brand panel. */
  .login-layout {
    grid-template-columns: 1.19fr 1fr;
  }

  .brand-panel {
    /* 54px against the mockup's 970px panel — 3.04% of the screen. Kept as a
       proportion rather than a fixed 4.5rem so the measure around the heading
       scales with it; IM Fell English sets ~14% wider than the mockup's own
       face, and a fixed inset left the heading wrapping near 960px. Capped
       where the display type caps, so it stops growing on very wide screens. */
    padding: 4rem min(3.04vw, 3.4rem);
  }

  /* Display type is sized off the panel, not the viewport: the mockup sets the
     heading at 9.41% of the panel width, and the panel is 54.3% of the screen,
     so 5.1vw reproduces it at any width. The cap stops it growing past the
     91px the mockup draws. Left at the phone sizing below this breakpoint,
     where the panel is full width and these ratios do not apply. */
  .display-title {
    font-size: clamp(3rem, 5.1vw, 5.7rem);
  }

  /* Same treatment: 1.94% of the panel, 18.8px at the drawn size. The 27em
     measure above sets the wrap, so it holds at either size. */
  .tagline {
    font-size: clamp(0.98rem, 1.05vw, 1.18rem);
  }

  /* Same treatment: 4.70% of the panel, 45.6px at the drawn size. */
  .countdown-value {
    font-size: clamp(1.7rem, 2.55vw, 2.85rem);
  }

  /* The box keeps the mockup's ~20px of breathing room around the larger
     numerals rather than collapsing onto them. */
  .countdown-unit {
    padding: 1.25rem 1.5rem;
  }

  .brand-illustration {
    display: block;
    /* 18.9% of the panel in the mockup; a flat 12rem drew it half again too
       large once the panel was corrected. */
    max-width: min(10.25vw, 11.4rem);
  }

  .form-panel {
    padding: 4rem 3rem;
  }

  /* 72px gutters around the 1066px column, as the mockup draws them. */
  .dashboard {
    max-width: calc(1066px + 144px);
    padding: 37px 72px 4rem;
  }

  /* The mockup's 651px and 391px columns, kept in proportion. */
  .dash-grid {
    grid-template-columns: 651fr 391fr;
  }
}
