/* ─────────────────────────────────────────────────────────────────
   style.css  –  Lake District PPGIS Survey

   Mobile first throughout: every size below is chosen for a phone held
   in one hand, and the layout simply centres itself on wider screens
   rather than rearranging into a desktop design.
   ───────────────────────────────────────────────────────────────── */

/* Border-box sizing everywhere, so a padded element is the width it says
   it is — without this, every width calculation below would need adjusting
   for its own padding and border. */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }


/* ── Palette ─────────────────────────────────────────────────────
   Defined once as custom properties. One spray colour per map question,
   matching the value given for the dots in that page's PAGE_CONFIG, so a
   change of scheme means editing two files rather than ten rules. The
   "-deep" pair are darker versions of the same hue, used only to tint the
   question headings, where small text needs more contrast than a dot does. */
:root {
    /* University-ish blue, used for structure rather than for data. */
    --primary:        #1a3f6f;
    --primary-dark:   #122d52;
    --primary-light:  #e8eef6;

    /* Q1 — familiarity. Blue. */
    --familiar:       #2563eb;
    --familiar-deep:  #1d4ed8;

    /* Q2 — importance. Purple. */
    --important:      #9333ea;
    --important-deep: #6b21a8;

    /* Neutrals. */
    --bg:             #f4f6f9;
    --card:           #ffffff;
    --border:         #dce1eb;
    --text:           #1e293b;
    --muted:          #64748b;

    /* Shared shape and depth, so every panel matches without repetition. */
    --radius:         10px;
    --shadow:         0 2px 8px rgba(0,0,0,0.07);
}


/* ── Base ────────────────────────────────────────────────────────  */

html {
    /* 16px root, so every rem below is a predictable multiple of it. */
    font-size: 16px;
    /* Suppresses the grey flash iOS paints over every tapped element, which
       on a page of buttons looks like a rendering fault. */
    -webkit-tap-highlight-color: transparent;
}

body {
    /* The system font stack: no web font to download, and the survey looks
       native on whatever device it is opened on. */
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    /* Generous leading, because the information sheet is a wall of text. */
    line-height: 1.5;
}

/* Caps the line length on a laptop and centres the survey; on a phone the
   max-width simply never applies. */
.page-container { max-width: 600px; margin: 0 auto; padding-bottom: 2rem; }

/* Utility used by every element that is toggled from JavaScript. !important
   because it must win over whatever display value the element already has. */
.hidden { display: none !important; }


/* ── Header ──────────────────────────────────────────────────────  */

.site-header {
    background: var(--primary);
    color: #fff;
    padding: 0.9rem 1.25rem;
    text-align: center;
}

.site-title { font-size: 1.05rem; font-weight: 700; }

/* The institution line is deliberately quiet: it establishes provenance
   without competing with the survey title. */
.institution {
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.8;
    margin-bottom: 0.2rem;
}


/* ── Progress ────────────────────────────────────────────────────
   Five steps. Knowing how much is left is what stops people abandoning
   part-way through a survey with four maps in it. */

.progress-wrap {
    background: var(--primary-dark);
    padding: 0.55rem 1.25rem 0.4rem;
}

.progress-bar {
    height: 5px;
    background: rgba(255,255,255,0.25);
    border-radius: 3px;
    /* Clips the fill to the rounded ends of the track. */
    overflow: hidden;
}

.progress-fill {
    height: 100%;
    background: #fff;
    border-radius: 3px;
    /* Animates if the width is ever changed from script. */
    transition: width 0.4s;
}

.progress-label {
    color: rgba(255,255,255,0.7);
    font-size: 0.72rem;
    margin-top: 0.3rem;
    text-align: right;
}


/* ── Cards ───────────────────────────────────────────────────────  */

.content { padding: 1rem 1rem 0; }

.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.2rem;
    margin-bottom: 0.9rem;
    box-shadow: var(--shadow);
}

.card h2 {
    font-size: 1rem;
    font-weight: 700;
    color: var(--primary);
    /* The rule underneath separates heading from body without a second
       background colour or an extra element. */
    padding-bottom: 0.55rem;
    margin-bottom: 0.8rem;
    border-bottom: 2px solid var(--primary-light);
}

.card p { font-size: 0.93rem; margin-bottom: 0.65rem; line-height: 1.65; }

/* No trailing gap inside the card. */
.card p:last-child { margin-bottom: 0; }

/* The anonymity promise, given a left bar so it reads as a standing
   commitment rather than as one more paragraph. */
.notice {
    background: var(--primary-light);
    border-left: 3px solid var(--primary);
    border-radius: 0 6px 6px 0;
    padding: 0.7rem 0.9rem;
    font-size: 0.88rem !important;
}


/* ── Form controls ───────────────────────────────────────────────  */

.form-group { margin-bottom: 1rem; }
.form-group:last-child { margin-bottom: 0; }

label.field-label {
    display: block;
    font-size: 0.88rem;
    font-weight: 600;
    margin-bottom: 0.38rem;
}

input[type="text"],
input[type="number"],
select,
textarea {
    width: 100%;
    /* Roomy padding: these are finger targets before they are text fields. */
    padding: 0.75rem 1rem;
    border: 2px solid var(--border);
    border-radius: 8px;
    /* 1rem exactly — iOS Safari zooms the whole page in on focus if an
       input's text is any smaller than 16px. */
    font-size: 1rem;
    font-family: inherit;
    color: var(--text);
    background: #fff;
    /* Strips the heavy native styling so the fields match each other. */
    -webkit-appearance: none;
    appearance: none;
    transition: border-color 0.2s;
}

/* A visible focus state is required for keyboard use; the default outline is
   replaced rather than simply removed. */
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--primary);
}

select {
    /* The native arrow went with appearance:none, so it is redrawn here as an
       inline SVG — no extra file to fetch. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748b' stroke-width='1.8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.9rem center;
    /* Keeps the longest option clear of the arrow. */
    padding-right: 2.4rem;
}

/* Vertical resize only: horizontal dragging would break the layout. */
textarea { min-height: 90px; resize: vertical; }


/* ── Radio and checkbox rows ─────────────────────────────────────
   The whole row is the label, so the tap target is the full width of the
   card rather than the 20px control itself. */

.option-group { display: flex; flex-direction: column; gap: 0.45rem; }

.option-row {
    display: flex;
    /* Top-aligned, so the control stays beside the first line of a long label
       rather than floating in the middle of a wrapped paragraph. */
    align-items: flex-start;
    gap: 0.7rem;
    padding: 0.7rem 0.9rem;
    border: 2px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.18s, background 0.18s;
    /* 48px is the usual minimum comfortable touch target. */
    min-height: 48px;
    /* Stops a double-tap selecting the label text instead of ticking the box. */
    -webkit-user-select: none;
    user-select: none;
}

.option-row:hover { border-color: var(--primary); background: var(--primary-light); }

.option-row input[type="radio"],
.option-row input[type="checkbox"] {
    width: 20px; height: 20px;
    /* Nudged down to sit on the text baseline. */
    margin-top: 0.1rem;
    /* Never squashed by a long label beside it. */
    flex-shrink: 0;
    accent-color: var(--primary);
    cursor: pointer;
    /* Undoes the shared input styling above, which does not suit a tickbox. */
    padding: 0; border: none; background: none;
}

.option-row span { font-size: 0.93rem; line-height: 1.45; }

/* The consent row carries the most text and the most weight, so it is tinted
   very slightly to set it apart from an ordinary option. */
.consent-row { background: #fafbff; }
.consent-row span { font-size: 0.88rem; }


/* ── Likert scale (nature connectedness) ─────────────────────────
   Ten statements, each answered on a 1-5 agreement scale. A row of five
   numbered columns rather than five separate option-rows: at five per
   statement, full-width rows would push the scale well past one screen,
   and the columns read at a glance as one continuous scale in a way that
   five stacked boxes would not. */

.likert-scale { display: flex; flex-direction: column; }

.likert-item {
    padding: 0.85rem 0;
    border-bottom: 1px solid var(--border);
}
/* No rule above the first statement or below the last — the card's own
   border already closes off the list at both ends. */
.likert-item:first-child { padding-top: 0; }
.likert-item:last-child  { padding-bottom: 0; border-bottom: none; }

.likert-statement { font-size: 0.9rem; line-height: 1.45; margin-bottom: 0.65rem; }

.likert-options {
    display: flex;
    /* Equal columns for 1 through 5, edge to edge across the card. */
    justify-content: space-between;
    gap: 0.3rem;
}

.likert-option {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    padding: 0.4rem 0 0.3rem;
    border-radius: 7px;
    cursor: pointer;
    transition: background 0.15s;
    /* Stops a tap selecting the number as text instead of picking the radio. */
    -webkit-user-select: none;
    user-select: none;
}

.likert-option:hover { background: var(--primary-light); }

/* :has() lets the whole column light up for the option that is actually
   selected, not just the 20px radio inside it — the same visual weight an
   option-row gets from its border, in a fifth of the width. */
.likert-option:has(input:checked) { background: var(--primary-light); }
.likert-option:has(input:checked) .likert-num { color: var(--primary); }

.likert-num {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--muted);
}

.likert-option input[type="radio"] {
    width: 20px; height: 20px;
    accent-color: var(--primary);
    cursor: pointer;
    padding: 0; border: none; background: none;
}


/* ── Buttons ─────────────────────────────────────────────────────  */

.btn {
    /* inline-flex centres the label and any arrow glyph together. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 0.85rem 1.75rem;
    border: none;
    border-radius: 8px;
    font-size: 0.95rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    /* Comfortably above the 44px minimum for a primary action. */
    min-height: 50px;
    letter-spacing: 0.02em;
    transition: background 0.18s, opacity 0.18s, transform 0.1s;
    -webkit-tap-highlight-color: transparent;
}

/* A press is confirmed by the button shrinking slightly — the only feedback
   a touch device gives, since there is no hover state. */
.btn:active { transform: scale(0.97); }

/* Disabled buttons are dimmed and do not react to a press at all, so a
   participant is never left wondering whether their tap registered. */
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn:disabled:active { transform: none; }

.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--primary-dark); }

.btn-secondary { background: #fff; color: var(--text); border: 2px solid var(--border); }
.btn-secondary:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); }

/* PREV on the left, NEXT on the right, in the same place on every page. */
.nav-buttons {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 1rem;
    margin-top: 1.1rem;
}

/* Page 1 has no PREV, so its single button is pushed to the right to stay
   where NEXT sits on every other page. */
.nav-buttons.end { justify-content: flex-end; }

/* The map pages fit a third button — SPRAY AGAIN — between PREV and NEXT.
   Equal thirds rather than the two-button pair's natural width, and a
   smaller side padding so "SPRAY AGAIN" fits one line on a narrow phone. */
.nav-buttons-3 { gap: 0.5rem; }
.nav-buttons-3 .btn { flex: 1; padding-left: 0.5rem; padding-right: 0.5rem; }


/* ── Map pages ───────────────────────────────────────────────────  */

.map-question { padding: 1rem 1rem 0.6rem; }

.map-question h2 {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--primary);
}

/* Each question is tinted to match the spray colour used to answer it, so
   the link between the question and the paint is immediate. */
.map-question.familiar  h2 { color: var(--familiar-deep); }
.map-question.important h2 { color: var(--important-deep); }

/* The subtext under each question's heading: present, but clearly
   subordinate to the question itself. */
.question-note {
    margin-top: 0.45rem;
    font-size: 0.85rem;
    color: var(--muted);
    line-height: 1.5;
}

/* How-to text. Quiet, because it is read once and then ignored. */
.instructions {
    margin: 0 1rem 0.7rem;
    padding: 0.7rem 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.83rem;
    color: var(--muted);
    line-height: 1.6;
}

/* Undo / Clear / Reset, sharing the width equally above the map. */
.map-toolbar {
    display: flex;
    gap: 0.45rem;
    margin: 0 1rem 0.5rem;
}

.tool-btn {
    /* Equal thirds regardless of label length. */
    flex: 1;
    padding: 0.55rem 0.4rem;
    border: 2px solid var(--border);
    border-radius: 7px;
    background: #fff;
    font-size: 0.78rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    color: var(--text);
    min-height: 42px;
    transition: border-color 0.18s, color 0.18s, background 0.18s;
}

.tool-btn:hover { border-color: var(--primary); color: var(--primary); }
.tool-btn:active { background: var(--primary-light); }

/* Positioning context for the layer switcher floating inside the map. */
.map-wrap { position: relative; margin: 0 1rem; }

#map {
    /* Viewport-relative, so the map fills the screen on a phone but is
       bounded on a laptop, with a floor that keeps it usable on a small
       device in landscape. */
    height: 65vh;
    min-height: 320px;
    max-height: 560px;
    border-radius: var(--radius);
    border: 2px solid var(--border);
    /* Clips the tiles to the rounded corners. */
    overflow: hidden;
    cursor: grab;
}


/* ── Base map switcher ───────────────────────────────────────────  */

.layer-switch {
    position: absolute;
    top: 10px;
    left: 10px;
    /* Above Leaflet's own panes (400) but below the modal overlay (2000). */
    z-index: 450;
    display: flex;
    background: #fff;
    border-radius: 6px;
    padding: 3px;
    /* A drop shadow is what separates it from the imagery behind it. */
    box-shadow: 0 2px 6px rgba(0,0,0,0.22);
    gap: 2px;
}

.layer-btn {
    padding: 4px 10px;
    border: none;
    border-radius: 4px;
    font-size: 0.73rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    color: var(--muted);
    background: transparent;
    min-height: 30px;
    transition: background 0.18s, color 0.18s;
}

/* The active base map is filled in, so which one is showing is never in doubt
   even when the imagery itself is ambiguous. */
.layer-btn.active { background: var(--primary); color: #fff; }


/* ── Spray colour buttons ────────────────────────────────────────  */

.draw-modes {
    display: flex;
    gap: 0.6rem;
    margin: 0.7rem 1rem 0;
}

.draw-btn {
    /* One button per map, spanning the full width of the row. */
    flex: 1;
    display: flex;
    /* Stacked: the label on top, the tap hint underneath. */
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    padding: 0.8rem 0.5rem;
    /* Transparent border reserved at full width, so the coloured border added
       below cannot shift the layout when it appears. */
    border: 2.5px solid transparent;
    border-radius: 8px;
    font-size: 0.78rem;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    text-align: center;
    min-height: 52px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    transition: all 0.2s;
}

/* The swatch and the button's name, kept on one line together while the
   hint below them forms the second line of the stack. */
.draw-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

/* A dot of the actual paint colour, so the button is identifiable by colour
   as well as by its label. */
.draw-btn .swatch {
    width: 14px; height: 14px;
    border-radius: 50%;
    flex-shrink: 0;
    /* A faint ring keeps the pale swatches visible on a pale button. */
    border: 2px solid rgba(0,0,0,0.25);
}

/* The armed state: an inset shadow and a ring in the button's own colour,
   which is the only signal that a finger drag will now paint rather than pan. */
.draw-btn.active {
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.18), 0 0 0 3px currentColor;
}

/* The button is a toggle, so it states what the next tap will do — in both
   states. Neither half of that is discoverable on its own: an unlabelled
   button gives no reason to press it, and getting stuck in spray mode with
   no way back to panning is the one way to be properly lost. */
.draw-btn::after {
    content: "tap to start";
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.7;
}

/* Same line, opposite instruction, once the can is in hand. Because the hint
   is present either way, the button does not change height when it is armed. */
.draw-btn.active::after { content: "tap to stop"; }

/* Q1 — familiar. Pale tint, saturated border, deep text: enough contrast to
   read, while the button still clearly belongs to its colour family. Q2
   follows the same recipe in its own hue. */
.btn-draw-familiar {
    background: rgba(37,99,235,0.10);
    color: #1e40af;
    border-color: var(--familiar);
}
.btn-draw-familiar.active, .btn-draw-familiar:hover {
    background: rgba(37,99,235,0.22);
    border-color: #1e40af;
}
.btn-draw-familiar .swatch { background: var(--familiar); }

/* Q2 — important. */
.btn-draw-important {
    background: rgba(147,51,234,0.10);
    color: #7e22ce;
    border-color: var(--important);
}
.btn-draw-important.active, .btn-draw-important:hover {
    background: rgba(147,51,234,0.22);
    border-color: #7e22ce;
}
.btn-draw-important .swatch { background: var(--important); }


/* ── Places count ─────────────────────────────────────────────────
   A quiet running total ("2 places added") beneath the draw button, so the
   participant has some feedback that "Spray again" is actually accumulating
   places rather than just resetting the map. */
.places-count {
    margin: 0.6rem 1rem 0;
    font-size: 0.8rem;
    color: var(--muted);
    text-align: center;
}


/* ── Follow-up sheet ─────────────────────────────────────────────
   A bottom sheet rather than a centred dialogue: it rises into the
   half of the screen a thumb can actually reach. */

.modal-overlay {
    position: fixed;
    /* Covers the viewport, so the map cannot be painted while it is open. */
    inset: 0;
    background: rgba(15,23,42,0.55);
    /* Above everything, Leaflet's controls included. */
    z-index: 2000;
    display: flex;
    /* Bottom-aligned: this is what makes it a sheet rather than a dialogue. */
    align-items: flex-end;
    justify-content: center;
}

.modal-sheet {
    background: var(--card);
    /* Rounded at the top only — the bottom edge is off-screen. */
    border-radius: 16px 16px 0 0;
    /* The safe-area inset clears the home indicator on a modern iPhone. */
    padding: 1.4rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom, 0px));
    width: 100%;
    max-width: 600px;
    /* Capped and scrollable, so an on-screen keyboard cannot push the
       buttons out of reach. */
    max-height: 80vh;
    overflow-y: auto;
    box-shadow: 0 -4px 24px rgba(0,0,0,0.18);
}

.modal-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--primary);
    padding-bottom: 0.6rem;
    margin-bottom: 0.9rem;
    border-bottom: 2px solid var(--primary-light);
}

/* The two sections of the sheet, spaced apart from each other and from the
   buttons below them. */
.slider-section  { margin: 0 0 1.1rem; }
.reasons-section { margin: 0 0 1.1rem; }

.slider-section .field-label,
.reasons-section .field-label { font-size: 0.9rem; margin-bottom: 0.5rem; }


/* ── Certainty slider ────────────────────────────────────────────
   The track takes whatever width is left once the value bubble beside
   it has been placed. */

.slider-row { display: flex; align-items: center; gap: 0.75rem; }

input[type="range"] {
    flex: 1;
    /* The native control cannot be styled, so it is replaced entirely. */
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 3px;
    background: var(--border);
    cursor: pointer;
    /* Overrides the shared input rules further up, which would otherwise
       give the track a border and a large padding. */
    padding: 0;
    border: none;
}

/* The thumb needs a vendor rule per engine — they cannot be combined into
   one selector, because an unrecognised selector invalidates the whole rule. */
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    /* 28px: a deliberately large target, since this is dragged with a thumb. */
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--primary);
    /* The white ring lifts the thumb off the track it sits on. */
    border: 3px solid #fff;
    box-shadow: 0 2px 5px rgba(0,0,0,0.22);
    cursor: pointer;
}

input[type="range"]::-moz-range-thumb {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--primary);
    border: 3px solid #fff;
    box-shadow: 0 2px 5px rgba(0,0,0,0.22);
    cursor: pointer;
}

/* The chosen value, shown as a numeral so the score is unambiguous — the
   thumb's position alone is hard to read to the nearest point. */
.slider-value {
    width: 40px; height: 40px;
    background: var(--primary);
    color: #fff;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: 1.05rem;
    /* Fixed size, so the layout does not shift between "–" and "10". */
    flex-shrink: 0;
}

/* Anchors the scale: without these the numbers alone say nothing about
   which end means what. */
.slider-endpoints {
    display: flex;
    justify-content: space-between;
    font-size: 0.73rem;
    color: var(--muted);
    margin-top: 0.3rem;
}


/* ── Thank you ───────────────────────────────────────────────────  */

.thankyou-card {
    text-align: center;
    padding: 2rem 1.5rem;
    margin: 1rem 1rem 0;
}

/* The tick is a text glyph in a circle: no icon font, no image request. */
.thankyou-card .tick {
    width: 64px; height: 64px;
    background: var(--primary-light);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    margin: 0 auto 1rem;
    font-size: 2rem;
}

.thankyou-card h2 { font-size: 1.4rem; color: var(--primary); margin-bottom: 0.65rem; }
.thankyou-card p { font-size: 0.93rem; color: var(--muted); margin-bottom: 0.5rem; }
