﻿/* The CSA module's stylesheet: the box builder (the harvest screen, the grid, the legend and one
   box) and the farmer-facing CSA pages that share its conventions.

   Phone-first on purpose. The harvest gets counted in a field, on a phone, with dirty hands — BoxBot's
   dense desktop grid is unusable there and it is the half of the week's work that does not happen at a
   desk. So the small-screen rules are the base and the desktop rules are the media query on top.

   Two things are load-bearing and tested rather than trusted:
     - .cc-tap is at least 44px in both directions. Every control a farmer presses carries it.
     - The harvest list and the compromise list reflow to one column at 375px.
   PhoneLayoutTests reads this file and fails the build if either goes.

   COLOURS COME FROM app.css. Every border, radius, surface and grey below is a var() onto the
   Portal's brand tokens (--border, --radius-*, --card-bg, --text-*) with the old raw Bootstrap hex
   kept only as the fallback after the comma, so a sheet that loads before app.css still renders.
   The one place a literal hex survives is the nine-way box/preference palette, and it survives on
   purpose - see the note above it.

   App.razor loads this sheet globally, which is why CsaTabBar can lean on .cc-tap from it and why
   the CSA page rules at the foot of this file reach the five farmer screens. */

/* ── Hit targets ──────────────────────────────────────────────────────────── */

.cc-tap,
.cc-tap.btn,
.cc-tap.form-control {
    min-height: 44px;
    min-width: 44px;
}

.cc-tap.form-check-label {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 44px;
}

/* ── Steps ────────────────────────────────────────────────────────────────── */

.cc-step {
    margin-bottom: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border, #e2dbd0);
}

/* ── 1. The harvest ───────────────────────────────────────────────────────── */

/* One row per crop. On a phone the name takes the full width and the number sits under it at a size a
   thumb can hit; there is no horizontal scrolling, because a table that scrolls sideways in a field is a
   table nobody fills in. */
.cc-harvest .list-group-item {
    flex-wrap: wrap;
    row-gap: .5rem;
}

.cc-harvest-name {
    flex: 1 1 100%;
    min-width: 0;
}

/* The number and its unit are ONE control, fixed in width, and the unit lives INSIDE it.

   The unit used to sit beside the field as an auto-width sibling, and this catalogue says "each", "bag",
   "lb" and "punnet" — four different widths — so the Perishable tick after it started at a different x on
   every row. That is the ragged right-hand column the owner reported. Both halves are fixed on purpose:
   pinning only the group moves the same bug one layer in, because a wide suffix would then eat the
   number's width instead of the tick's position. HarvestRowAlignmentTests holds both. */
.cc-harvest-qty-group {
    flex: 0 0 13rem;
    max-width: 13rem;
}

/* Wide enough for the value, not for the storage precision. 6.5rem clipped "262.50" mid-number at
   1.1rem once the spin buttons took their share; the displayed value is now trimmed (BoxBuilderCopy.Field)
   AND the field fits a five-figure count with two decimals. 13rem of group less 4rem of suffix leaves the
   number the same 9rem it always had, and the whole group is still well inside one column at 375px, which
   PhoneLayoutTests holds. */
.cc-harvest-qty {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 1.1rem;
    text-align: right;
}

/* The unit, as the field's suffix. Fixed width and clipped rather than allowed to grow: a farm whose unit
   word is longer than this must not be the farm whose rows go ragged. Nothing is lost when it clips — the
   line above the field already reads "stock says 40 punnet", and the input's aria-label names the unit for
   a screen reader. Padding trimmed from Bootstrap's .75rem so "punnet" fits inside the 4rem. */
.cc-harvest-unit {
    flex: 0 0 4rem;
    width: 4rem;
    padding-left: .25rem;
    padding-right: .25rem;
    justify-content: center;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: .85rem;
}

@media (min-width: 576px) {
    .cc-harvest-name {
        flex: 1 1 auto;
    }
}

/* ── 2. The dials ─────────────────────────────────────────────────────────── */

.cc-dial {
    border: 1px solid var(--border, #e2dbd0);
    border-radius: var(--radius-lg, 6px);
    padding: .75rem;
    height: 100%;
}

.cc-dial legend {
    float: none;
    width: auto;
    font-weight: 600;
}

/* The typed dial value: a farmer who wants 5 or 7 is not limited to the presets above it. Narrow, so it
   reads as one more control on the dial rather than as the dial. */
.cc-dial-number {
    max-width: 16rem;
}

/* ── The preview ──────────────────────────────────────────────────────────── */

/* Numbers and short labels. No speedometer gauges: the arc encodes nothing the number does not, it reads
   badly to a screen reader, and it cannot be compared precisely — which is the whole job. */
.cc-stat {
    border: 1px solid var(--border, #e2dbd0);
    border-radius: var(--radius-lg, 6px);
    padding: .75rem;
    height: 100%;
}

.cc-stat-value {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.1;
}

.cc-stat-label {
    font-size: .85rem;
}

/* The compromise list is the primary output, so it reads as a list of sentences and not as a table of
   codes. At 375px each line stacks: text, then its actions. */
.cc-compromises .list-group-item {
    padding: .75rem;
}

@media (max-width: 575.98px) {
    .cc-compromises .btn {
        width: 100%;
        text-align: left;
    }

    .cc-stats > [class*="col-"] {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/* ── 3. The grid ──────────────────────────────────────────────────────────── */

.cc-grid-group {
    margin-top: 1rem;
}

.cc-grid-heading {
    font-size: .9rem;
    font-weight: 600;
    margin-bottom: .35rem;
}

.cc-grid {
    display: grid;
    gap: .5rem;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
}

/* On a phone the heat map degrades to a single-column list — a wall of 9.5rem squares on a 375px screen
   is two per row and a very long scroll, and the list carries the same words. */
@media (max-width: 575.98px) {
    .cc-grid {
        grid-template-columns: 1fr;
    }
}

.cc-box {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    align-items: flex-start;
    text-align: left;
    padding: .5rem;
    border: 1px solid var(--border, #e2dbd0);
    border-radius: var(--radius-lg, 6px);
    background: var(--card-bg, #fff);
    min-height: 5.5rem;
}

.cc-box-open {
    outline: 2px solid var(--accent, #d97746);
    outline-offset: 1px;
}

.cc-box-member {
    font-weight: 600;
    font-size: .9rem;
}

.cc-box-value,
.cc-box-state {
    font-size: .78rem;
}

/* The word inside the square. Colour is the pattern; this is the meaning, and it is never optional. */
.cc-box-state {
    font-weight: 600;
}

.cc-box-thumbs {
    display: flex;
    gap: .15rem;
    margin-top: auto;
}

/* THE ONE PLACE A LITERAL HEX BELONGS IN THIS SHEET, and it is declared once here rather than typed
   twice.

   This is a fourteen-way CATEGORICAL scale — nine kinds of problem and five preference levels — and
   app.css's brand tokens are a five-way semantic scale (success / warning / danger / info / accent).
   Mapping fourteen onto five would either collapse categories that must stay distinguishable or
   invent token names that mean nothing outside this screen, so the scale keeps its own values and
   gets its own named variables instead. Renaming, not recolouring: every rendered colour below is
   byte-identical to what it was, and ColourHasTextEquivalentTests still holds that none of them is
   ever the only channel.

   Each value was previously written out twice — once on the square's left border and once on the
   legend's dot — with nothing keeping the two in step. Now the legend and the square read the same
   variable, so a colour cannot drift between the key and the thing it is a key to. */
:root {
    --csa-box-ok:       #198754;
    --csa-box-under:    #dc3545;
    --csa-box-over:     #fd7e14;
    --csa-box-short:    #6f42c1;
    --csa-box-missed:   #0dcaf0;
    --csa-box-thin:     #ffc107;
    --csa-box-spoiling: #20c997;
    --csa-box-disliked: #d63384;
    --csa-box-empty:    #adb5bd;

    --csa-pref-never: var(--csa-box-disliked);
    --csa-pref-less:  var(--csa-box-thin);
    --csa-pref-ok:    var(--csa-box-empty);
    --csa-pref-more:  #6ea8fe;
    --csa-pref-love:  var(--csa-box-ok);
}

/* Colour is the CATEGORY of problem and the left border's weight is its severity — one amber for
   everything is what makes BoxBot's heat map unreadable. Every one of these has a word beside it in the
   legend and inside the square; none of them is the only channel. */
.cc-box.box-ok       { border-left: 4px solid var(--csa-box-ok); }
.cc-box.box-under    { border-left: 6px solid var(--csa-box-under); }
.cc-box.box-over     { border-left: 4px solid var(--csa-box-over); }
.cc-box.box-short    { border-left: 6px solid var(--csa-box-short); }
.cc-box.box-missed   { border-left: 4px solid var(--csa-box-missed); }
.cc-box.box-thin     { border-left: 4px solid var(--csa-box-thin); }
.cc-box.box-spoiling { border-left: 4px solid var(--csa-box-spoiling); }
.cc-box.box-disliked { border-left: 6px solid var(--csa-box-disliked); }
.cc-box.box-empty    { border-left: 4px solid var(--csa-box-empty); }

/* ── The legend ───────────────────────────────────────────────────────────── */

.cc-legend {
    margin: .75rem 0;
    font-size: .8rem;
}

.cc-legend-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1rem;
    margin-bottom: .35rem;
}

.cc-legend-heading {
    font-weight: 600;
}

.cc-swatch {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    white-space: nowrap;
}

.cc-swatch-dot {
    width: .75rem;
    height: .75rem;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid rgba(0, 0, 0, .25);
    flex: 0 0 auto;
}

.cc-swatch.pref-never  .cc-swatch-dot { background: var(--csa-pref-never); }
.cc-swatch.pref-less   .cc-swatch-dot { background: var(--csa-pref-less); }
.cc-swatch.pref-ok     .cc-swatch-dot { background: var(--csa-pref-ok); }
.cc-swatch.pref-more   .cc-swatch-dot { background: var(--csa-pref-more); }
.cc-swatch.pref-love   .cc-swatch-dot { background: var(--csa-pref-love); }

.cc-swatch.box-ok       .cc-swatch-dot { background: var(--csa-box-ok); }
.cc-swatch.box-under    .cc-swatch-dot { background: var(--csa-box-under); }
.cc-swatch.box-over     .cc-swatch-dot { background: var(--csa-box-over); }
.cc-swatch.box-short    .cc-swatch-dot { background: var(--csa-box-short); }
.cc-swatch.box-missed   .cc-swatch-dot { background: var(--csa-box-missed); }
.cc-swatch.box-thin     .cc-swatch-dot { background: var(--csa-box-thin); }
.cc-swatch.box-spoiling .cc-swatch-dot { background: var(--csa-box-spoiling); }
.cc-swatch.box-disliked .cc-swatch-dot { background: var(--csa-box-disliked); }
.cc-swatch.box-empty    .cc-swatch-dot { background: var(--csa-box-empty); }

/* ── Thumbnails ───────────────────────────────────────────────────────────── */

/* A produce box rendered as a spreadsheet is the loudest thing wrong with both competitors. Every item on
   every screen gets one of these, and a farm with no photos gets a letter rather than a hole. */
.cc-thumb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: var(--radius-md, 4px);
    flex: 0 0 auto;
    background: var(--content-bg, #e9ecef);
}

.cc-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* A thumbnail whose picture is a class declared once on the page (ProductPictureCss, #498) rather than an
   <img> per square. Sized and cropped the way the <img> above is. */
.cc-thumb-pic {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

.cc-thumb-sm { width: 2rem;   height: 2rem; }
.cc-thumb-md { width: 2.75rem; height: 2.75rem; }
.cc-thumb-xs { width: 1.5rem;  height: 1.5rem; }
.cc-thumb-lg { width: 4rem;    height: 4rem; }
.cc-thumb-lg .cc-thumb-initials { font-size: 1rem; }

/* A gallery tile, where the picture IS the content rather than a label beside one: it takes the width it
   is given and a fixed, modest height. Still a .cc-thumb, so a row whose image never uploaded shows the
   product's letters instead of a broken icon. */
.cc-thumb-tile {
    display: flex;
    width: 100%;
    height: 8.75rem;
}

.cc-thumb-tile .cc-thumb-initials { font-size: 1.5rem; }

.cc-thumb-initials {
    font-weight: 700;
    font-size: .75rem;
    color: var(--text-secondary, #4f6855);
}

/* ── One box ──────────────────────────────────────────────────────────────── */

.cc-candidates {
    max-height: 22rem;
    overflow-y: auto;
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THE CSA FARMER PAGES — shares & sites, orders, one order, pack day, customers

   Phone-first like everything above it: the 375px rules are the base and the desktop behaviour is
   the media query on top. These five screens carried nothing but Bootstrap's .table-responsive,
   which is a horizontal scrollbar and no indication that there is anything to scroll to.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── The page heading ─────────────────────────────────────────────────────────────────────────── */

/* The "CSA" heading sits directly under a 58px dark top bar that is position:sticky. At 375px
   .cc-page's padding drops to 20px and the heading ends up crowded against the bar — it reads as
   clipped, which is what the phone review reported. Space below the bar, and a scroll-margin so the
   heading still clears the bar when anything scrolls it into view rather than landing behind it. */
.cc-csa-head {
    margin-top: .75rem;
    margin-bottom: .25rem;
    scroll-margin-top: calc(var(--topnav-height, 58px) + .5rem);
}

@media (min-width: 576px) {
    .cc-csa-head {
        margin-top: 0;
    }
}

/* ── Tables ───────────────────────────────────────────────────────────────────────────────────── */

/* A CSA table lives inside a card, the way every table in the design mockups does: one bordered
   block with the column heads inside it rather than a bare grid floating on the page background.
   The card owns the border, so the table's own outer edge would double it. */
.cc-csa-table-card {
    margin-bottom: 1rem;
}

.cc-csa-table-card > .table-responsive {
    margin-bottom: 0;
}

.cc-csa-table-card .table {
    margin-bottom: 0;
}

/* The scroll affordance. .table-responsive scrolls and says nothing, so on a phone a wide table
   looks like a table with its right-hand columns simply missing. A fade pinned to the right edge of
   the scroll box says there is more, and it is painted with background-attachment: local so it
   disappears once the reader has scrolled to the end — an affordance that lies about a table that
   is already fully visible is worse than none. */
@media (max-width: 575.98px) {
    .cc-csa-table-card > .table-responsive {
        background:
            linear-gradient(to right, var(--card-bg, #fff), rgba(255, 255, 255, 0)) left center,
            linear-gradient(to left, var(--card-bg, #fff), rgba(255, 255, 255, 0)) right center,
            linear-gradient(to right, rgba(28, 42, 30, .13), rgba(255, 255, 255, 0)) left center,
            linear-gradient(to left, rgba(28, 42, 30, .13), rgba(255, 255, 255, 0)) right center;
        background-repeat: no-repeat;
        background-size: 2rem 100%, 2rem 100%, .75rem 100%, .75rem 100%;
        background-attachment: local, local, scroll, scroll;
    }
}

/* A summary row inside a table - "The season", with the figure beside it. It was Bootstrap's
   `tr.table-light`, i.e. the same grey band this sheet has just taken off the column heads, so it
   would have been the only grey left on the page. The house surface behind it and a rule above,
   which is what the design mockups do with a totals row. */
.cc-csa-total-row > * {
    background: var(--content-bg, #faf8f4);
    border-top: 1px solid var(--border, #e2dbd0);
}

/* A card nested inside another card - the share form's "What this season comes to" panel. It was
   Bootstrap's .bg-body-tertiary, which is a grey that belongs to no palette here. A card on the
   page's own background reads as inset without needing a second border weight. */
.cc-csa-inset {
    background: var(--content-bg, #faf8f4);
}

/* The value folded under its neighbour when its own column is hidden on a phone. Nothing is
   deleted at 375px — a column that will not fit moves under the cell it belongs with, so the
   sentence "Tue 22 Sep, Riverbend Farm Stand" is still readable on the narrowest phone. */
.cc-csa-sub {
    display: block;
    font-size: .8125rem;
    line-height: 1.35;
    color: var(--text-muted, #5b7662);
}

/* ── Progressive disclosure ───────────────────────────────────────────────────────────────────── */

/* Shares & sites opened with four paragraphs of explanation above the fold, which is three more
   than a farmer who has been here before needs. The secondary half of each explanation moves in
   here: still on the page, still findable, no longer between the reader and the list.

   A native <details> rather than a Blazor toggle on purpose — it needs no circuit round-trip, it
   works before the page is interactive, and the browser gives it the right keyboard and screen
   reader semantics for free. */
.cc-csa-more {
    margin: .25rem 0 .75rem;
}

.cc-csa-more > summary {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 2rem;
    cursor: pointer;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--accent-strong, #b8501f);
    list-style: none;
}

.cc-csa-more > summary::-webkit-details-marker {
    display: none;
}

/* The chevron is drawn here rather than taken from the marker so it can rotate, and it is never
   the only signal — the summary is a sentence a reader can act on with the triangle hidden. */
.cc-csa-more > summary::before {
    content: "";
    width: .4rem;
    height: .4rem;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform .12s ease;
}

.cc-csa-more[open] > summary::before {
    transform: rotate(45deg);
}

.cc-csa-more > summary:hover {
    color: var(--accent-hover, #c0612e);
}

.cc-csa-more-body {
    margin: .5rem 0 0;
    font-size: .875rem;
    line-height: 1.5;
    color: var(--text-secondary, #4f6855);
}

/* ── The CSA setup checklist ──────────────────────────────────────────────────────────────────── */

/* Four-and-a-bit steps between switching the module on and handing over the first box, drawn on the
   Shares & sites page (CsaSetupCard.razor). It borrows Setup.razor's LOOK — a numbered disc, a tick
   once the step is behind you, the next one called out — and none of its machinery: Setup is a
   1,566-line wizard and this is a list of links.

   Every size here is rem. The module rescales the day the Portal's fixed 14px root is raised, and
   one px declaration is one element that opts out of that forever (CsaTextScaleTests). */
.cc-csa-setup-lede {
    font-size: .875rem;
}

.cc-csa-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: .5rem;
}

.cc-csa-step {
    display: flex;
    align-items: flex-start;
    gap: .625rem;
    padding: .5rem .625rem;
    border: 1px solid transparent;
    border-radius: .375rem;
}

/* The step a farmer is on. A tinted surface AND a left rule AND the word "Next:" above the list —
   three channels, because the tint alone is the thing eight percent of men cannot see. */
.cc-csa-step.is-next {
    background: var(--content-bg, #faf8f4);
    border-color: var(--border, #e2dbd0);
    border-left: 3px solid var(--accent-strong, #b8501f);
}

.cc-csa-step-num {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background: var(--content-bg, #faf8f4);
    border: 1px solid var(--border, #e2dbd0);
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-secondary, #4f6855);
}

/* A finished step goes quiet. It still carries the word "Done" beside its title — the colour is the
   second channel here, never the only one. */
.cc-csa-step.is-done .cc-csa-step-num {
    background: var(--success-light, #e7f3ea);
    border-color: var(--success-light, #e7f3ea);
    color: var(--success-text, #1f6b3a);
}

.cc-csa-step.is-done .cc-csa-step-detail {
    display: none;
}

.cc-csa-step-body {
    display: block;
    min-width: 0;
}

.cc-csa-step-title {
    display: block;
    font-size: .875rem;
    font-weight: 600;
}

.cc-csa-step-detail {
    display: block;
    margin-top: .125rem;
    font-size: .8125rem;
    line-height: 1.45;
    color: var(--text-secondary, #4f6855);
}

.cc-csa-step-link {
    display: inline-block;
    margin-top: .25rem;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--accent-strong, #b8501f);
}

/* ── "Nobody can join there" ──────────────────────────────────────────────────────────────────── */

/* A share whose site has no price is MISCONFIGURED, and a share that is closed was closed on
   purpose. Those looked identical to a member — the member page drops an unpriced share entirely,
   so the farm reads as shut — and they must not look identical to the farmer either. The warning is
   words first; this only gives it room. */
.cc-csa-warn {
    display: block;
    margin-top: .125rem;
    font-size: .8125rem;
    line-height: 1.35;
    color: var(--warning-text, #8a5a11);
}

/* The spaces-left line folded under the member count on a list row. Same treatment as .cc-csa-sub,
   which it sits beside — a number a farmer scans down a column rather than reads. */
.cc-csa-spots {
    display: block;
    font-size: .8125rem;
    line-height: 1.35;
    color: var(--text-muted, #5b7662);
}
