/*
 * GIG Retrospective - semi dark, greyed blue, with hue reserved for the board columns.
 *
 * Everything is scoped under .gig-retro and sets its own values rather than inheriting,
 * because this has to look the same dropped into whatever theme the site runs.
 */

/*
 * Palette note: every colour used for text clears WCAG AA (4.5:1) against the surface
 * it sits on. The backgrounds were darkened a little to buy that headroom, so the
 * greyed-blue character survives - it is the same palette, just no longer murky.
 *
 * The board columns are the one deliberate exception to the greyed blue: they carry
 * meaning, so they carry hue - green for what to do more of, red for what to stop,
 * orange for what to ease off. See the .gig-col[data-col] block for how each column
 * splits into an outline colour, a faded wash and a lighter tint for text.
 *
 * Type note: --gig-fs is the single dial for the whole component. Every other size is
 * a calc() off it, so bumping that one value rescales headings, labels, buttons and
 * captions together instead of leaving the small text behind. It is deliberately not
 * rem: rem follows the theme's root size, which we do not control.
 */
.gig-retro {
    --gig-bg: #171c23;
    --gig-surface: #1f262f;
    --gig-surface-2: #262f3a;
    --gig-surface-3: #2e3947;
    --gig-border: #3f4c5c;
    --gig-border-soft: #33404e;

    --gig-text: #eaf0f7;   /* 13.3:1 on surface */
    --gig-dim: #b6c4d4;    /*  8.6:1 - labels and secondary lines */
    --gig-faint: #9aa9bb;  /*  5.8:1 - author names, counts, captions */

    --gig-blue-1: #9dc0e4;
    --gig-blue-2: #86a9d0;
    --gig-blue-3: #6f92bb;
    --gig-blue-4: #4d6d90;
    --gig-blue-5: #3d5b7a;

    --gig-hot: #b0cdeb;
    --gig-danger: #d98d97;  /* 5.3:1 */
    --gig-ok: #8fc0a2;      /* 7.4:1 */

    /*
     * The five column identity colours, defined once because two things use them: the
     * column itself, and the bar on a ticket showing which column it was written in.
     * Kept in one place so those two can never drift apart.
     *
     * These are spread across the hue circle rather than grouped by meaning. Three
     * shades of one green told the eye apart only by lightness, which measured 8.2 in
     * OKLab between START DOING and DO MORE - close enough to be a guess in a live
     * session. Spreading the hues puts the closest pair at 16.5, and no two columns are
     * now within 16. The cost is that the positives no longer share a colour family;
     * the column headings carry that meaning instead.
     */
    --gig-col-0: #9bd75a;   /* START DOING - lime */
    --gig-col-1: #35b6a4;   /* DO MORE     - teal */
    --gig-col-2: #d9534f;   /* STOP DOING  - red */
    --gig-col-3: #e8973c;   /* DO LESS     - orange */
    --gig-col-4: #7e8ff5;   /* KEEP DOING  - indigo */

    /* Type scale. Change --gig-fs alone to resize the whole board. */
    --gig-fs: 16px;
    --gig-fs-2xs: calc(var(--gig-fs) * .70);   /* 11.2 - badges */
    --gig-fs-xs:  calc(var(--gig-fs) * .78);   /* 12.5 - field labels, table heads */
    --gig-fs-sm:  calc(var(--gig-fs) * .83);   /* 13.3 - small buttons, authors */
    --gig-fs-md:  calc(var(--gig-fs) * .88);   /* 14.1 - captions, notices */
    --gig-fs-lg:  calc(var(--gig-fs) * .94);   /* 15.0 - buttons, tables, meta */
    --gig-fs-h1:  calc(var(--gig-fs) * 1.65);
    --gig-fs-h2:  calc(var(--gig-fs) * 1.40);
    --gig-fs-h3:  calc(var(--gig-fs) * 1.18);
    --gig-fs-h4:  calc(var(--gig-fs) * 1.06);

    /* Softer, larger corners than the original flat 6px, with smaller variants so
       chips and buttons stay in proportion instead of looking like cut-down cards. */
    --gig-radius: 12px;
    --gig-radius-sm: 8px;
    --gig-radius-xs: 6px;

    /* Depth is carried by shadow rather than by lighter surfaces, so none of the
       text-contrast ratios documented above move. */
    --gig-shadow-1: 0 1px 2px rgba(0, 0, 0, .28);
    --gig-shadow-2: 0 4px 14px rgba(0, 0, 0, .34);
    --gig-shadow-3: 0 10px 30px rgba(0, 0, 0, .45);
    --gig-ring: 0 0 0 3px rgba(134, 169, 208, .30);

    --gig-ease: cubic-bezier(.2, .7, .3, 1);

    background: var(--gig-bg);
    color: var(--gig-text);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: var(--gig-fs);
    line-height: 1.55;
    border-radius: var(--gig-radius);
    overflow: hidden;
    margin: 0 0 2rem;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

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

/* One keyboard ring for the whole component, so nothing is ever focused invisibly. */
.gig-retro :focus-visible {
    outline: 2px solid var(--gig-hot);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .gig-retro *, .gig-retro *::before, .gig-retro *::after {
        transition-duration: .01ms !important;
        animation-duration: .01ms !important;
    }
}

/* ---------- standalone: the board owns the whole browser window ---------- */

.gig-standalone-html,
.gig-standalone-body {
    margin: 0;
    padding: 0;
    min-height: 100%;
    background: #171c23;
}

.gig-standalone-body {
    /* Nothing from the theme is loaded here, so set the page's own baseline. */
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    color: #eaf0f7;
    -webkit-text-size-adjust: 100%;
}

/* Anything the host left on the board page around the shortcode. */
.gig-standalone-body > * { max-width: none; }

.gig-standalone-body .gig-retro {
    margin: 0;
    border-radius: 0;
    width: auto;
    max-width: none;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

.gig-standalone-body .gig-body { flex: 1 1 auto; }

/* Edge-to-edge on a phone, where every pixel of column width counts. */
@media (max-width: 640px) {
    .gig-standalone-body .gig-body { padding: .9rem .75rem 1.5rem; }
    .gig-standalone-body .gig-header { padding: .8rem .85rem; }
}

/*
 * Embedded mode: when the board sits inside a normal themed page, most themes wrap
 * content in a narrow reading column, which squeezes five columns into something
 * unusable. There it breaks out of that column and centres itself. Standalone pages
 * are excluded - they have no column to escape.
 */
@media (min-width: 1100px) {
    body:not(.gig-standalone-body) .gig-retro {
        width: min(94vw, 1680px);
        /* The theme sets max-width on the content column; without this it still wins. */
        max-width: none;
        margin-left: calc(50% - min(47vw, 840px));
        margin-right: 0;
        box-shadow: var(--gig-shadow-3);
    }
}

.gig-retro p { margin: 0 0 .65rem; }
.gig-retro h1, .gig-retro h2, .gig-retro h3, .gig-retro h4 {
    margin: 0 0 .55rem;
    font-weight: 650;
    color: var(--gig-text);
    line-height: 1.25;
    letter-spacing: -.011em;
}
.gig-retro h1 { font-size: var(--gig-fs-h1); }
.gig-retro h2 { font-size: var(--gig-fs-h2); }
.gig-retro h3 { font-size: var(--gig-fs-h3); }
.gig-retro h4 { font-size: var(--gig-fs-h4); }

.gig-retro a {
    color: var(--gig-blue-1);
    text-decoration: none;
    text-underline-offset: .18em;
}
.gig-retro a:hover { text-decoration: underline; }

.gig-retro ul { margin: .3rem 0 .55rem 1.15rem; padding: 0; }
.gig-retro li { margin: .2rem 0; }

/* ---------- header ---------- */

.gig-header {
    display: flex;
    align-items: center;
    gap: 1.15rem;
    padding: 1rem 1.4rem;
    /* The containing block for the centred Deftpower mark below. */
    position: relative;
    background: linear-gradient(180deg, #232d39 0%, #1c242e 100%);
    border-bottom: 1px solid var(--gig-border);
    /* The old 2px blue rule read as a divider. A hairline glow under it keeps the
       accent without a hard stripe fighting the rounded corners. */
    box-shadow: 0 1px 0 rgba(157, 192, 228, .22), var(--gig-shadow-1);
    flex-wrap: wrap;
}

.gig-brand-mark {
    width: 42px; height: 42px;
    border-radius: var(--gig-radius-sm);
    /* Stops at blue-3, not blue-4: the dark corner of the gradient has to keep the
       "GIG" lettering above 4.5:1, and blue-4 dropped it to 3.4:1. */
    background: linear-gradient(145deg, var(--gig-blue-1), var(--gig-blue-3));
    display: grid; place-items: center;
    font-weight: 800; font-size: var(--gig-fs-lg); color: #10171f;
    letter-spacing: -.03em;
    flex: none;
    box-shadow: var(--gig-shadow-1);
}

/*
 * For a host the mark renders as a link back to the session portal. It has to out-rank
 * the generic .gig-retro a rule, which would otherwise repaint the "GIG" lettering in
 * link blue on top of its own light blue gradient.
 */
.gig-retro a.gig-brand-mark {
    color: #10171f;
    text-decoration: none;
    cursor: pointer;
    transition: transform .12s var(--gig-ease), box-shadow .15s var(--gig-ease), filter .15s var(--gig-ease);
}

.gig-retro a.gig-brand-mark:hover {
    text-decoration: none;
    filter: brightness(1.08);
    transform: translateY(-1px);
    box-shadow: var(--gig-shadow-2);
}

.gig-retro a.gig-brand-mark:active {
    transform: translateY(0);
    box-shadow: var(--gig-shadow-1);
}

.gig-brand-name {
    font-size: calc(var(--gig-fs) * 1.5);
    font-weight: 700;
    letter-spacing: -.02em;
    color: #f2f7fd;
}

.gig-brand-by {
    font-size: var(--gig-fs-xs);
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--gig-blue-1);
    padding-left: 1.15rem;
    border-left: 1px solid var(--gig-border);
}

/*
 * The running version, sat after the byline. Deliberately quiet - it is reference
 * information, not part of the brand - but --gig-faint still clears AA on this ground.
 */
.gig-brand-version {
    align-self: center;
    font-size: var(--gig-fs-xs);
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--gig-faint);
    background: rgba(0, 0, 0, .22);
    border: 1px solid var(--gig-border-soft);
    border-radius: 999px;
    padding: .1rem .55rem;
    white-space: nowrap;
    flex: none;
}

.gig-header-spacer { flex: 1 1 auto; }

/*
 * The Deftpower wordmark in the header.
 *
 * Absolutely positioned rather than laid out in the flex row, because the row has to
 * stay one line. Centring a flex item needs the items either side to be equal-width
 * columns; the brand block runs to roughly 560px and the mark to 315px, so equal
 * columns would demand about 1440px of header before anything wrapped, and a 1280px
 * laptop would get the two-row header this arrangement exists to avoid. Taken out of
 * flow, the mark is centred on the header's own axis - padding is symmetric, so 50% of
 * the padding box is the visual centre - and neither side block is disturbed.
 *
 * The trade is that it can only be centred while there is room for it, which is what
 * the 1100px query below deals with.
 */
/*
 * The default is the safe one: a centred line of its own, ordered last so the brand block
 * and the session meta keep sharing the first line. This is what renders with JavaScript
 * off, and at any width, and it can never collide with anything.
 */
.gig-header-logo-link {
    display: block;
    flex: 0 0 100%;
    order: 1;
    margin: .2rem auto 0;
    text-align: center;
    line-height: 0;
    border-radius: var(--gig-radius-xs);
    text-decoration: none;
}

/*
 * Lifted onto the header's own axis only when fitHeaderLogo() has measured the row and
 * found the clearance for it. A media query cannot make this call: the right-hand side
 * carries the session name, phase, vote count and host name, so its width is a property
 * of the session rather than of the viewport. Measured on a 1600px board, that side runs
 * to 681px and a breakpoint tuned to the portal screen puts the mark 31px on top of the
 * Sign out button.
 */
.gig-header.is-logo-centred {
    /* Room for a 56px mark plus the 1rem padding either side; the 42px brand block would
       otherwise size the header and let the mark hang out of it. */
    min-height: calc(56px + 2rem);
}

.gig-header.is-logo-centred .gig-header-logo-link {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: inline-block;
    flex: none;
    order: 0;
    margin: 0;
    width: auto;
}

.gig-header-logo-link:focus-visible {
    outline: 2px solid var(--gig-hot);
    outline-offset: 3px;
}

/* Near-white already, so opacity reads where brightness would not - as in the footer. */
.gig-header-logo-link:hover .gig-header-logo { opacity: 1; }

.gig-header-logo {
    height: 56px;
    /* Pins the box before the SVG arrives; width:auto alone collapses to 0. */
    aspect-ratio: 276 / 49;
    width: auto;
    max-width: 100%;
    display: block;
    /* Centres the mark on its own line in the stacked layout. text-align on the link
       cannot do it - this is a block box, so it ignores the parent's text alignment.
       Inert in the centred layout, where the link shrink-wraps the image. */
    margin: 0 auto;
    /* A touch held back, so a prominent mark still does not outshout the board. */
    opacity: .94;
    transition: opacity .15s var(--gig-ease);
}

.gig-header-meta {
    display: flex; align-items: center; gap: .9rem; flex-wrap: wrap;
    font-size: var(--gig-fs-lg); color: var(--gig-dim);
}

.gig-header-meta strong { color: var(--gig-text); font-weight: 650; }

@media (max-width: 720px) {
    .gig-brand-by { padding-left: 0; border-left: none; }
}

@media (max-width: 640px) {
    /* Matches the footer's own step-down, so the two marks stay in proportion. */
    .gig-header-logo { height: 40px; }
}

/* ---------- layout ---------- */

.gig-body { padding: 1.35rem 1.4rem 1.8rem; }
.gig-narrow { max-width: 560px; margin: 1.75rem auto; }

/*
 * The session portal. Wider than the join column it shares a page with, because a
 * five-column table carrying a full invite URL cannot live in 560px.
 */
.gig-narrow.gig-wide { max-width: 940px; }

/*
 * Wide tables scroll inside their own box rather than forcing the card wider or, worse,
 * letting the browser crush the invite-link column into one character per line.
 */
.gig-tablewrap {
    overflow-x: auto;
    margin-top: .7rem;
}

.gig-tablewrap > table { min-width: 660px; }

/* Long, unbreakable URLs need a floor, or the column collapses under table layout. */
.gig-tablewrap .gig-invite { min-width: 13rem; }

.gig-card {
    background: var(--gig-surface);
    border: 1px solid var(--gig-border-soft);
    border-radius: var(--gig-radius);
    padding: 1.25rem;
    box-shadow: var(--gig-shadow-1);
}

.gig-card + .gig-card { margin-top: 1rem; }

.gig-muted { color: var(--gig-dim); }
.gig-faint { color: var(--gig-faint); font-size: var(--gig-fs-md); }
.gig-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.gig-spread { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }

/* ---------- forms ---------- */

.gig-retro label {
    display: block;
    margin: .8rem 0 .3rem;
    font-size: var(--gig-fs-xs);
    color: var(--gig-dim);
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
}

.gig-retro input[type=text],
.gig-retro input[type=email],
.gig-retro input[type=password],
.gig-retro input[type=url],
.gig-retro input[type=number],
.gig-retro input[type=date],
.gig-retro select,
.gig-retro textarea {
    width: 100%;
    max-width: 100%;
    padding: .55rem .7rem;
    background: var(--gig-bg);
    border: 1px solid var(--gig-border);
    border-radius: var(--gig-radius-sm);
    color: var(--gig-text);
    font-family: inherit;
    /* Full size, not shrunk: anything under 16px makes iOS Safari zoom the page on focus. */
    font-size: var(--gig-fs);
    line-height: 1.45;
    transition: border-color .15s var(--gig-ease), box-shadow .15s var(--gig-ease);
}

.gig-retro input:focus,
.gig-retro select:focus,
.gig-retro textarea:focus {
    outline: none;
    border-color: var(--gig-blue-2);
    box-shadow: var(--gig-ring);
}

.gig-retro textarea { resize: vertical; min-height: 62px; }

.gig-retro button {
    font-family: inherit;
    font-size: var(--gig-fs-lg);
    font-weight: 600;
    padding: .5rem .95rem;
    border-radius: var(--gig-radius-sm);
    border: 1px solid var(--gig-border);
    background: var(--gig-surface-2);
    color: var(--gig-text);
    cursor: pointer;
    line-height: 1.35;
    box-shadow: var(--gig-shadow-1);
    transition: background .15s var(--gig-ease), border-color .15s var(--gig-ease),
                box-shadow .15s var(--gig-ease), transform .1s var(--gig-ease);
}

.gig-retro button:hover:not(:disabled) {
    background: var(--gig-surface-3);
    border-color: var(--gig-blue-4);
    box-shadow: var(--gig-shadow-2);
}
.gig-retro button:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--gig-shadow-1); }
.gig-retro button:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }

.gig-retro button.gig-primary { background: var(--gig-blue-4); border-color: var(--gig-blue-3); color: #f0f6fc; }
/* Must stay dark enough for the near-white label: blue-3 would drop this to 3:1. */
.gig-retro button.gig-primary:hover:not(:disabled) { background: #506f95; border-color: var(--gig-blue-2); }
.gig-retro button.gig-danger { color: var(--gig-danger); }
.gig-retro button.gig-danger:hover:not(:disabled) { background: #3b2a2f; border-color: var(--gig-danger); }
.gig-retro button.gig-small { padding: .26rem .6rem; font-size: var(--gig-fs-sm); border-radius: var(--gig-radius-xs); }
/* Deeper than .gig-primary so the two never look alike, and still 6.1:1. */
.gig-retro button.gig-on { background: var(--gig-blue-5); border-color: var(--gig-blue-1); color: #f0f6fc; }

.gig-error { color: var(--gig-danger); font-size: var(--gig-fs-md); margin-top: .55rem; }
.gig-notice { color: var(--gig-ok); font-size: var(--gig-fs-md); margin-top: .55rem; }

/* ---------- host bar ---------- */

.gig-hostbar {
    display: flex; flex-wrap: wrap; gap: .8rem 1.2rem; align-items: flex-end;
    background: linear-gradient(180deg, var(--gig-surface-2) 0%, var(--gig-surface) 100%);
    border: 1px solid var(--gig-border-soft);
    border-left: 4px solid var(--gig-blue-2);
    border-radius: var(--gig-radius);
    padding: .9rem 1.1rem;
    margin-bottom: 1.1rem;
    box-shadow: var(--gig-shadow-1);
}

.gig-hostbar label { margin: 0 0 .28rem; }
.gig-hostgroup { display: flex; flex-direction: column; }
.gig-hostgroup select { min-width: 140px; }

.gig-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .24rem .65rem;
    border-radius: 999px;
    background: var(--gig-surface-2);
    border: 1px solid var(--gig-border);
    font-size: var(--gig-fs-sm);
    color: var(--gig-dim);
}

.gig-invite {
    display: block;
    background: var(--gig-bg);
    border: 1px dashed var(--gig-border);
    border-radius: var(--gig-radius-sm);
    padding: .42rem .6rem;
    font-family: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace;
    font-size: var(--gig-fs-md);
    color: var(--gig-blue-1);
    word-break: break-all;
}

/*
 * The invite link and its Copy button, side by side.
 *
 * The row wraps rather than letting the link shrink away: with min-width: 0 the URL
 * collapsed to about 50px in the host bar while the button kept its full width, which
 * is worse than no button at all. A floor on the link plus wrapping means the button
 * drops underneath when the space really is too tight.
 */
.gig-invite-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem;
}

.gig-invite-row .gig-invite {
    flex: 1 1 12rem;
    min-width: 11rem;
}

.gig-invite-row button {
    flex: none;
    /* A stable width, so the label swapping to "Copied" does not shuffle the layout. */
    min-width: 4.4rem;
}

.gig-pill {
    display: inline-block;
    padding: .18rem .6rem; border-radius: 999px; font-size: var(--gig-fs-2xs); font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
    background: var(--gig-blue-5); color: #f0f6fc;
}

/* ---------- board ---------- */

.gig-board {
    display: grid;
    grid-template-columns: repeat(5, minmax(210px, 1fr));
    gap: 1rem;
    align-items: start;
}

@media (max-width: 1280px) { .gig-board { grid-template-columns: repeat(2, minmax(210px, 1fr)); } }
@media (max-width: 640px)  { .gig-board { grid-template-columns: 1fr; } }

.gig-col {
    /*
     * background-color and background-image are set separately, not through the
     * shorthand: the wash is a per-column gradient over the shared surface, and the
     * shorthand would reset one every time the other is overridden.
     */
    background-color: var(--gig-surface);
    /*
     * A fixed fade distance, not a percentage: with a percentage the tint stretches to
     * the column's height, so a column holding one ticket looks more strongly coloured
     * than one holding six. 180px gives every column the same tinted band under its
     * heading whatever it contains.
     */
    background-image: linear-gradient(180deg, var(--gig-wash) 0, var(--gig-wash-off) 180px);
    border: 1px solid var(--gig-line);
    border-radius: var(--gig-radius);
    padding: .85rem .75rem;
    min-height: 160px;
    box-shadow: var(--gig-shadow-1);
    transition: border-color .15s var(--gig-ease), background-color .15s var(--gig-ease), box-shadow .15s var(--gig-ease);
}

/* The column accent used to be a hard 3px top border. As a rounded inner bar it still
   codes the column, without five heavy stripes ruling across the top of the board.
   Full strength here: this is the outline colour, matching the column's own border. */
.gig-col::before {
    content: "";
    display: block;
    height: 3px;
    border-radius: 999px;
    background: var(--gig-line);
    margin: 0 0 .65rem;
}

/* Drop target stays neutral-bright rather than a stronger tint: it has to read the same
   way on all five columns, including the two dark ones. */
.gig-col.gig-droptarget {
    border-color: var(--gig-hot);
    background-color: var(--gig-surface-2);
    box-shadow: var(--gig-shadow-2), 0 0 0 1px var(--gig-hot);
}

.gig-col-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; margin-bottom: .6rem; }
.gig-col-title { font-size: var(--gig-fs-sm); font-weight: 800; letter-spacing: .09em; color: var(--gig-accent); }
.gig-col-count {
    font-size: var(--gig-fs-sm); font-weight: 650; color: var(--gig-faint);
    background: var(--gig-surface-2); border-radius: 999px; padding: .05rem .5rem; flex: none;
}

/*
 * Column colours, by meaning rather than by position: greens for what the team should
 * do more of, red for what it should stop, orange for what it should ease off.
 *
 * Three tokens per column, because one cannot serve all three jobs:
 *   --gig-line    the outline: column border and the bar above the heading.
 *   --gig-wash    the same colour at low alpha, fading out by mid-column.
 *   --gig-accent  a lighter tint of the same hue, used wherever the colour becomes TEXT
 *                 (the column heading) or a small mark on a ticket.
 *
 * A saturated line colour is rarely legible as text on this ground, so each column also
 * carries a lighter tint of the same hue for its heading. Those run 5.49:1 to 6.50:1,
 * comfortably past the 4.5:1 AA needs, while every line colour clears the 3:1 that
 * non-text contrast asks of the border and the bar.
 * --gig-line is only ever outline or bar, where 3:1 non-text contrast is the bar, and
 * every value clears it. --gig-wash-off is the same hue at zero alpha rather than
 * "transparent", so the fade never dips through grey on the way out.
 */
.gig-col[data-col="0"] {   /* START DOING - lime */
    --gig-line: var(--gig-col-0);
    --gig-accent: #9bd75a;
    --gig-wash: rgba(155, 215, 90, .14);
    --gig-wash-off: rgba(155, 215, 90, 0);
}

.gig-col[data-col="1"] {   /* DO MORE - teal */
    --gig-line: var(--gig-col-1);
    --gig-accent: #46c3b0;
    --gig-wash: rgba(53, 182, 164, .14);
    --gig-wash-off: rgba(53, 182, 164, 0);
}

.gig-col[data-col="2"] {   /* STOP DOING - red */
    --gig-line: var(--gig-col-2);
    --gig-accent: #ff837b;
    --gig-wash: rgba(217, 83, 79, .14);
    --gig-wash-off: rgba(217, 83, 79, 0);
}

.gig-col[data-col="3"] {   /* DO LESS - orange */
    --gig-line: var(--gig-col-3);
    --gig-accent: #ef9e44;
    --gig-wash: rgba(232, 151, 60, .14);
    --gig-wash-off: rgba(232, 151, 60, 0);
}

.gig-col[data-col="4"] {   /* KEEP DOING - indigo */
    --gig-line: var(--gig-col-4);
    --gig-accent: #96a9ff;
    --gig-wash: rgba(126, 143, 245, .14);
    --gig-wash-off: rgba(126, 143, 245, 0);
}

/* ---------- tickets ---------- */

.gig-ticket {
    position: relative;
    background: var(--gig-surface-2);
    border: 1px solid var(--gig-border-soft);
    border-radius: var(--gig-radius-sm);
    padding: .65rem .7rem .6rem .9rem;
    margin-bottom: .6rem;
    cursor: grab;
    box-shadow: var(--gig-shadow-1);
    transition: border-color .15s var(--gig-ease), box-shadow .15s var(--gig-ease),
                transform .12s var(--gig-ease), background .15s var(--gig-ease);
}

/*
 * The accent edge as an inset bar rather than a border, so it follows the radius.
 *
 * It takes the colour of the column the ticket was WRITTEN in, not the one it currently
 * sits in, so a ticket dragged or grouped into another column still says where it came
 * from. --gig-origin is set per ticket below; the column's own --gig-accent is only a
 * fallback for a payload that predates the origin being recorded.
 */
.gig-ticket::before {
    content: "";
    position: absolute;
    left: .32rem; top: .55rem; bottom: .55rem;
    width: 3px;
    border-radius: 999px;
    background: var(--gig-origin, var(--gig-accent, var(--gig-blue-3)));
    opacity: .8;
}

/* Written in START DOING, wherever it has ended up since. */
.gig-ticket[data-origin="0"] { --gig-origin: var(--gig-col-0); }
.gig-ticket[data-origin="1"] { --gig-origin: var(--gig-col-1); }
.gig-ticket[data-origin="2"] { --gig-origin: var(--gig-col-2); }
.gig-ticket[data-origin="3"] { --gig-origin: var(--gig-col-3); }
.gig-ticket[data-origin="4"] { --gig-origin: var(--gig-col-4); }

/*
 * A ticket that has left its original column gets a slightly wider, fully opaque bar.
 * Colour alone cannot carry this - the greens are close together and red/green is the
 * axis colour-blind viewers lose - so the bar itself changes shape as a second cue,
 * with the origin column named in the ticket's title attribute as a third.
 */
.gig-ticket[data-moved="1"]::before {
    width: 5px;
    opacity: 1;
}

.gig-ticket:hover {
    border-color: var(--gig-border);
    box-shadow: var(--gig-shadow-2);
    transform: translateY(-1px);
}
.gig-ticket.gig-selected { border-color: var(--gig-hot); box-shadow: 0 0 0 2px var(--gig-hot), var(--gig-shadow-2); }
.gig-ticket.gig-mine { background: var(--gig-surface-3); }
.gig-ticket.gig-dragging { opacity: .4; transform: none; box-shadow: none; }

/*
 * Collect phase, on the host's screen only: the ticket is there, the shape of it is
 * there, the words are not. Participants are never sent other people's tickets, so this
 * rule has nothing to do with keeping them out - it only stops the host reading ahead.
 *
 * A host who opens devtools can of course read the text; they are entitled to. The blur
 * is a nudge against reading early, not a security boundary.
 */
.gig-ticket.gig-concealed {
    cursor: default;
    /* No hover lift: nothing here responds to a click. */
    transform: none;
}

.gig-ticket.gig-concealed:hover {
    transform: none;
    box-shadow: var(--gig-shadow-1);
    border-color: var(--gig-border-soft);
}

.gig-ticket.gig-concealed .gig-ticket-text {
    filter: blur(5px);
    /* Selecting it would put readable text on the clipboard and undo the whole point. */
    user-select: none;
    -webkit-user-select: none;
    pointer-events: none;
}

/* The note explaining why a column shows fewer tickets than it counts. */
.gig-collect-note {
    margin: 0 0 1.1rem;
}

.gig-ticket-text { white-space: pre-wrap; word-break: break-word; line-height: 1.5; }

.gig-ticket-foot { display: flex; justify-content: space-between; align-items: center; gap: .5rem; margin-top: .5rem; }
.gig-author { font-size: var(--gig-fs-sm); color: var(--gig-faint); font-weight: 600; }

.gig-votes { display: flex; align-items: center; gap: .25rem; }

.gig-vote-count {
    min-width: 1.75rem; text-align: center; font-weight: 700; font-size: var(--gig-fs-md);
    padding: .1rem .4rem; border-radius: 999px;
    background: var(--gig-blue-5); color: #f0f6fc;
}

.gig-vote-count.gig-zero { background: var(--gig-surface); color: var(--gig-faint); }
.gig-vote-mine { font-size: var(--gig-fs-sm); color: var(--gig-blue-1); }

.gig-group {
    border: 1px solid var(--gig-blue-4);
    border-radius: var(--gig-radius-sm);
    padding: .55rem;
    margin-bottom: .65rem;
    background: rgba(59, 88, 117, .18);
    box-shadow: var(--gig-shadow-1);
}

.gig-group-head { display: flex; justify-content: space-between; align-items: center; gap: .4rem; margin-bottom: .45rem; flex-wrap: wrap; }
.gig-group-title { font-weight: 700; font-size: var(--gig-fs-lg); color: var(--gig-blue-1); word-break: break-word; }

.gig-badge {
    font-size: var(--gig-fs-2xs); text-transform: uppercase; letter-spacing: .08em;
    color: var(--gig-faint); border: 1px solid var(--gig-border); border-radius: 999px; padding: .05rem .45rem;
}

/* ---------- tables ---------- */

.gig-retro table { width: 100%; border-collapse: collapse; font-size: var(--gig-fs-lg); background: none; }
.gig-retro th {
    text-align: left; font-size: var(--gig-fs-xs); text-transform: uppercase; letter-spacing: .07em;
    color: var(--gig-dim); padding: .5rem .6rem; border-bottom: 1px solid var(--gig-border);
    background: none;
}
.gig-retro td { padding: .6rem; border-bottom: 1px solid var(--gig-border-soft); vertical-align: top; color: var(--gig-text); background: none; }
.gig-retro tbody tr:last-child td { border-bottom: none; }

/* ---------- misc ---------- */

.gig-preview { background: var(--gig-bg); border: 1px solid var(--gig-border-soft); border-radius: var(--gig-radius-sm); padding: 1rem; margin-top: .8rem; }
.gig-flash { position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 9999; max-width: 380px; }
.gig-flash > div {
    background: var(--gig-surface-3); color: var(--gig-text);
    border: 1px solid var(--gig-border); border-left: 4px solid var(--gig-blue-2);
    border-radius: var(--gig-radius-sm); padding: .7rem .9rem; margin-top: .45rem;
    font-size: var(--gig-fs-lg); box-shadow: var(--gig-shadow-3);
}
.gig-flash > div.gig-bad { border-left-color: var(--gig-danger); }

/* An error waits to be read; only the reader clears it. */
.gig-flash > div.gig-sticky { cursor: pointer; }

.gig-flash-dismiss {
    display: block;
    margin-top: .35rem;
    font-size: var(--gig-fs-sm);
    color: var(--gig-faint);
}

.gig-adminlink {
    font-size: var(--gig-fs-md);
    color: var(--gig-blue-1);
    border: 1px solid var(--gig-border);
    border-radius: 999px;
    padding: .18rem .7rem;
    text-decoration: none;
    transition: background .15s var(--gig-ease), border-color .15s var(--gig-ease);
}
.gig-adminlink:hover { background: var(--gig-surface-2); border-color: var(--gig-blue-4); text-decoration: none; }


.gig-retro ::placeholder { color: var(--gig-faint); opacity: 1; }

.gig-banner {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    background: var(--gig-surface-2);
    border: 1px solid var(--gig-border-soft);
    border-left: 4px solid var(--gig-blue-1);
    border-radius: var(--gig-radius);
    padding: .9rem 1.1rem;
    margin-bottom: 1.1rem;
    box-shadow: var(--gig-shadow-1);
}

.gig-banner-text { flex: 1 1 260px; }
.gig-banner-title { font-weight: 700; color: var(--gig-text); font-size: var(--gig-fs-h4); }
.gig-banner-note { color: var(--gig-dim); font-size: var(--gig-fs-lg); }

/* ---------- footer ---------- */

.gig-footer {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    flex-wrap: wrap;
    padding: 1.1rem 1.4rem;
    border-top: 1px solid var(--gig-border-soft);
    background: var(--gig-surface);
    color: var(--gig-dim);
    font-size: var(--gig-fs-lg);
}

/* The Deftpower mark, left. Links to deftpower.com - see FOOTER_LOGO_URL. The link is
   the image, so it needs its own focus ring for anyone tabbing through. */
.gig-footer-link {
    display: inline-block;
    /* Never let the flex row shrink the mark away; it collapsed to 0 wide without this. */
    flex: 0 0 auto;
    border-radius: var(--gig-radius-xs);
    line-height: 0;
    text-decoration: none;
}

/* The mark is already near-white, so brightening it does nothing; opacity reads instead. */
.gig-footer-link:hover .gig-footer-logo { opacity: 1; }

.gig-footer-link:focus-visible {
    outline: 2px solid var(--gig-hot);
    outline-offset: 3px;
}

/*
 * The Deftpower wordmark: a wide lockup with no ground of its own, so no radius and no
 * plate behind it. Sized by height so the aspect ratio is never touched. 34px, not the
 * 64px the old square-ish mark used - at 276x49 that would run 360px across the footer.
 */
.gig-footer-logo {
    height: 34px;
    /* An unloaded image with width:auto collapses to 0 inside a flex row, which then
       stops it ever loading. Pinning the ratio reserves the right box up front. */
    aspect-ratio: 276 / 49;
    width: auto;
    max-width: 100%;
    display: block;
    /* Slightly held back so the brand mark does not outshout the board above it. */
    opacity: .92;
    transition: opacity .15s var(--gig-ease);
}

.gig-footer-text { color: var(--gig-dim); }

/*
 * The Gecko IT Group mark, lower right. 44px rather than the Deftpower mark's 34px
 * because this lockup is far squarer - 2.25:1 against 5.6:1 - so at an equal height it
 * reads as the smaller of the two.
 *
 * margin-left:auto rather than a spacer element before it. A spacer absorbs the slack on
 * its own flex line only, so on a phone - where the footer wraps and the mark takes a
 * line of its own - the mark would sit bottom LEFT, which is the opposite of the corner
 * it was asked to occupy. An auto margin holds the right edge of whichever line it lands
 * on.
 */
/*
 * The link is the flex item now that the mark is wrapped in one, so the auto margin and
 * the no-shrink live here rather than on the image. Left on the image they would do
 * nothing, and the mark would drift back to the left of its line.
 */
.gig-footer-gig-link {
    display: block;
    flex: 0 0 auto;
    margin-left: auto;
    line-height: 0;
    border-radius: var(--gig-radius-xs);
    text-decoration: none;
}

.gig-footer-gig-link:focus-visible {
    outline: 2px solid var(--gig-hot);
    outline-offset: 3px;
}

/* Near-white already, so opacity reads where brightness would not - as with the other two. */
.gig-footer-gig-link:hover .gig-footer-gig-logo { opacity: 1; }

.gig-footer-gig-logo {
    height: 44px;
    /* Pins the box before the PNG lands; width:auto alone collapses to 0 in a flex row. */
    aspect-ratio: 396 / 176;
    width: auto;
    max-width: 100%;
    display: block;
    opacity: .95;
    transition: opacity .15s var(--gig-ease);
}

@media (max-width: 640px) {
    .gig-footer { padding: .9rem .75rem; gap: .8rem; }
    .gig-footer-logo { height: 28px; }
    /* Steps down with the Deftpower mark, keeping the two in proportion. */
    .gig-footer-gig-logo { height: 34px; }
}

/* In standalone mode the body flexes, so the footer settles at the bottom of the
   window even when a session has only a couple of tickets in it. */
.gig-standalone-body .gig-footer { margin-top: auto; }
