/* input(545,41): run-time error CSS1026: Expected open brace, found 'selector('
input(690,1): run-time error CSS1019: Unexpected token, found '.'
input(2588,29): run-time error CSS1030: Expected identifier, found '#showM511Data'
input(2588,42): run-time error CSS1025: Expected comma or open brace, found ')' */
/*
 * Permit Central design layer — extracted from Connie's mockups.
 *
 * The mockups are rendered by a React "dc-runtime" and carry almost all of their
 * styling as inline style attributes: 3,310 of them across the eleven page
 * designs, collapsing to 437 distinct declarations. The <style> blocks in those
 * files are runtime scaffolding (.sc-*, x-dc, #dc-root) plus a small reset, and
 * are deliberately NOT ported here.
 *
 * Inline styles cannot be used in this product (strict CSP, see CLAUDE.md), so
 * the design is expressed as tokens plus component classes. This file defines
 * the values and the most-repeated components; per-page classes are added as
 * each view is converted.
 *
 * The component classes take effect only where a view opts into them, so the
 * conversion stays reviewable one page at a time. The tokens and the data-grid
 * rules at the foot of this file are the exception: they apply as soon as the
 * file is linked, which is how a tenant's typography reaches the staff grid.
 *
 * TENANT OVERRIDES
 * Every token below falls back to the design's own value but defers to the
 * per-organization custom properties emitted by OrganizationThemeTokens. An
 * organization that sets brandColour or fontFamily retints this layer without
 * any change here — that is the seam between Connie's design and a customer's
 * published style guide.
 */

:root {
	/* ---- Typeface -------------------------------------------------------
	 * Archivo is self-hosted (see BetaDashboard.css). A tenant naming its own
	 * face in fontFamily replaces it; Roboto is self-hosted for Toronto.
	 */
	--pc-font: var(--permit-font-family, Archivo, system-ui, sans-serif);

	/* ---- Type scale -----------------------------------------------------
	 * The design is dense: 13px carries the interface (579 uses), with 12.5px
	 * and 12px for secondary text. Toronto's Web Design System mandates 18px
	 * body text, so --pc-text-base defers to the tenant's fontSizeBase and the
	 * steps are derived from it rather than hard-coded. A tenant that sets
	 * nothing gets the design exactly as drawn.
	 */
	--pc-text-base: var(--permit-font-size-base, 13px);
	--pc-text-xs: calc(var(--pc-text-base) - 2px);      /* 11px  */
	--pc-text-sm: calc(var(--pc-text-base) - 1.5px);    /* 11.5px */
	--pc-text-md: calc(var(--pc-text-base) - 0.5px);    /* 12.5px */
	--pc-text-lg: calc(var(--pc-text-base) + 0.5px);    /* 13.5px */
	--pc-text-xl: calc(var(--pc-text-base) + 3.5px);    /* 16.5px */

	--pc-leading-tight: 1.3;
	--pc-leading-body: var(--permit-line-height-base, 1.4);

	/* ---- Tabular density ------------------------------------------------
	 * Tabular data sits a step below body text once a tenant raises the base
	 * size. A cap rather than a subtraction, so the design as drawn is
	 * untouched — at the default 13px this resolves to 13px and changes
	 * nothing — while an organization that sets 18px for prose gets 16px in a
	 * grid. That keeps a staff list scannable without asking the tenant to
	 * configure two sizes, or to choose between its style guide and its tools.
	 *
	 * Raised 15px -> 16px: Toronto's review names 16px as the floor for text,
	 * and a grid full of 15px sat a pixel under it. One pixel rather than the
	 * three that reaching 18px would need, so the columns this cap exists to
	 * protect keep their measured widths.
	 */
	--pc-table-text-max: 16px;
	--pc-table-text: min(var(--pc-text-base), var(--pc-table-text-max));

	/*
	 * Column headings derive from the table text rather than from the raw base.
	 * The --pc-text-* steps subtract a fixed number of pixels, which holds at the
	 * design's 13px but not at Toronto's 18px: "xs" resolved to 16px there, all
	 * but body size, and uppercase labels stopped fitting columns they were
	 * measured to fit. Deriving from the capped table size keeps the heading a
	 * heading at either end of the range.
	 */
	--pc-table-head-text: calc(var(--pc-table-text) - 3px);

	/* A chip inside the grid follows the table, not the body. Left on the body
	 * scale it grew to 17px at an 18px base — larger than the 15px data around it
	 * — and a "Pending Payment" chip then overran a column measured at 16px.
	 */
	--pc-table-chip-text: calc(var(--pc-table-text) - 2px);

	/* Comfortable reading measure. In ch so it follows the tenant: a larger base
	 * size gives larger text on shorter lines, which is the point of raising it.
	 * ch measures the "0" glyph, wider than average lowercase, so this lands a
	 * little under the character count it reads as. */
	--pc-measure: 65ch;

	/* ---- Ink ------------------------------------------------------------ */
	--pc-ink: var(--permit-text-colour, #242c3a);       /* primary text, 467 uses */
	/* The design's secondary grey is #7a8798. It does not meet WCAG AA as text:
	 * 3.65:1 on white, 3.41:1 on the subtle surface, against a 4.5:1 requirement,
	 * and it was the single cause of 471 contrast failures across the site — every
	 * record count, every second line in a grid cell, every hint.
	 *
	 * Darkened in HLS with hue and saturation held, so it stays the same grey and
	 * reads as the design intends: 5.37:1 on white, 5.02:1 on #f6f7fa, 4.87:1 on
	 * #f1f4f9, which is every background it is used against.
	 *
	 * All three defer to a tenant that has published a text colour. Toronto's
	 * guide says every font is #000000 and means it, and the greys below were
	 * the whole of the gap: prose in #59637a where the standard allows one ink.
	 * The cost is this layer's three tiers of emphasis collapsing into one for
	 * such a tenant, which is a real loss — but a grey a published guide does
	 * not permit is not ours to keep. Tenants that publish nothing are untouched.
	 */
	--pc-ink-muted: var(--permit-text-colour, #606c7b);  /* secondary text, 249   */
	--pc-ink-soft: var(--permit-text-colour, #59637a);   /* tertiary text, 204    */
	--pc-ink-strong: var(--permit-text-colour, #333d4d);

	/* ---- Brand ----------------------------------------------------------
	 * The design's blue is #1e40af. Toronto's is #165788; setting brandColour
	 * swaps it everywhere this token is used.
	 */
	--pc-brand: var(--permit-brand-colour, #1e40af);

	/* The supporting four are derived from brandColour on the server, because a
	 * readable chip needs to know how light the brand is and CSS cannot ask. The
	 * fallbacks are the design's own values, so a tenant that sets nothing is
	 * rendered exactly as drawn. See PermitCore/Organization/BrandPalette.cs.
	 */
	--pc-brand-tint: var(--permit-brand-tint, #eff4ff);     /* chip / selected background */
	--pc-brand-border: var(--permit-brand-border, #d7e2fa);
	--pc-brand-ink: var(--permit-brand-ink, var(--pc-brand));

	/* Text on the brand itself — a filled button. White suits the design's own
	 * blue and every brand dark enough to carry it; a light brand gets the
	 * near-black instead, decided where the contrast maths is. */
	--pc-on-brand: var(--permit-brand-on, #ffffff);

	/* ---- Surfaces -------------------------------------------------------- */
	--pc-surface: #ffffff;
	--pc-surface-subtle: #f7faff;
	--pc-surface-muted: #f1f4f9;
	--pc-surface-sunken: #f4f7fc;

	/* ---- Status ---------------------------------------------------------- */
	--pc-danger: #b42318;
	--pc-warning: #7a5a00;

	/* ---- Radii -----------------------------------------------------------
	 * The mockups use eight radii (5, 6, 7, 8, 10, 12, 20, 50%). Consolidated
	 * to four steps plus a pill; the dropped values differ by a pixel and did
	 * not correspond to distinct component families.
	 */
	--pc-radius-sm: 5px;
	--pc-radius-md: 7px;
	--pc-radius-lg: 10px;
	--pc-radius-xl: 12px;
	--pc-radius-pill: 999px;
}

/* ======================================================================
 * Components
 *
 * The twelve declarations below account for 640 of the 3,310 inline styles.
 * Near-duplicates in the source are folded together where they differed only
 * in a line-height or a fixed-versus-clamped size — those were drafting
 * artefacts, not distinct intents.
 * ====================================================================== */

/* Status and category chip. The single most repeated element, 136 uses. */
.pc-chip {
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
	border-radius: var(--pc-radius-sm);
	padding: 3px 7px;
	font: 500 var(--pc-text-sm) / 1.35 var(--pc-font);
	background: var(--pc-brand-tint);
	color: var(--pc-brand-ink);
	border: 1px solid var(--pc-brand-border);
}

/*
 * Status variants. These are semantic, not brand: a rejected permit reads red
 * whichever organization is looking at it, so they do not follow brandColour.
 * Every pair is at least 4.5:1 against its own background, checked rather than
 * eyeballed, because this product has to meet AODA.
 */
.pc-chip--approved   { background: #e9f7ef; color: #1b6e3c; border-color: #bfe3cd; }  /* 5.69:1 */
.pc-chip--review     { background: #eef2ff; color: #4338ca; border-color: #d3dafe; }  /* 7.07:1 */
.pc-chip--pending    { background: #fdf7e6; color: #7a5a00; border-color: #e8d9a8; }  /* 5.96:1 */
.pc-chip--payment    { background: #fff4ed; color: #9a3412; border-color: #f6d3bd; }  /* 6.76:1 */
.pc-chip--revision   { background: #fdf2f8; color: #9d174d; border-color: #f4cfe0; }  /* 7.22:1 */
.pc-chip--rejected   { background: #fdf1f0; color: #b42318; border-color: #f3c9c4; }  /* 5.95:1 */
.pc-chip--incomplete { background: #f1f4f9; color: #4d5768; border-color: #dbe2ec; }  /* 6.62:1 */

/* Form field label. 155 uses across two near-identical source variants. */

/* Help text under a field or value. 103 uses across two source variants. */

/* Body copy inside a table cell or panel. 86 uses across two source variants. */

/* Heading that is also a link — used for record titles in lists. 45 uses. */

/* Square icon button, e.g. the language and overflow controls. 45 uses. */

/* Small count or initial badge. 42 uses. */

/* Unstyled button used to wrap a custom control. 38 uses. */

/* ======================================================================
 * Data grids
 * ====================================================================== */

/*
 * The staff application grid. Widths come from the server (TableHeaderDto);
 * this only sets the density, so a tenant whose style guide raises the base
 * text size still gets a grid it can scan.
 */
#permitTable {
	font-size: var(--pc-table-text);
}

/*
 * Stacked grid cells. A column holds a value with a quieter second line under
 * it — an application id over its permit type, a work window over its length —
 * so two related facts share one column's width instead of taking two.
 *
 * The note inherits the cell's size rather than setting its own, so it follows
 * the tenant's typography down the same scale as everything else.
 */
#permitTable .pc-cell-primary {
	display: block;
}

#permitTable .pc-cell-note {
	display: block;
	margin-top: 1px;
	font-size: 0.85em;
	color: var(--pc-ink-muted);
}

/*
 * Grid chrome, following the mockup: a white header with quiet uppercase
 * labels, hairline rules between rows, and no banding.
 *
 * Scoped to .pc-grid, the wrapper on PermitTable.cshtml, rather than to the
 * table id: bootstrap-table clones the header into a separate table that
 * carries no id, so the visible header is not reachable that way.
 *
 * Bootstrap 5 paints table backgrounds through --bs-table-bg and an inset
 * box-shadow rather than background-color, so these override the variables. The
 * global .table-light (#23527c) and .table-striped (#D1EBFF) rules in Site.css
 * are left alone — 47 and 39 other views still depend on them.
 *
 * None of this is tenant branding: that navy was a product default, not an
 * organization's colour. What a tenant controls — typeface, text size, text
 * colour, brand colour — still arrives through the tokens, so Toronto's links
 * render in its own #165788 and its body text stays #000000.
 */
/*
 * Fixed layout on both tables. bootstrap-table renders the header as a second
 * table, and only the body one carries the id, so scoping this to #permitTable
 * left the header on auto layout: it sized itself to its label plus the sort
 * arrow and drifted up to 40px out of step with the columns beneath it.
 */
.pc-grid .table {
	table-layout: fixed;
	--bs-table-bg: var(--pc-surface);
	--bs-table-color: var(--pc-ink);
	--bs-table-striped-bg: transparent;
	--bs-table-striped-color: var(--pc-ink);
	--bs-table-hover-bg: var(--pc-surface-subtle);
	--bs-table-hover-color: var(--pc-ink);
}

/*
 * The same chrome on a table whose columns are not measured for it.
 *
 * .pc-grid exists for the application list, where TableHeaderDto sends widths
 * and bootstrap-table needs a fixed layout to keep its cloned header in step.
 * Every other list in the product -- staff groups, drawing templates, type
 * groups, invoices -- is a plain table whose columns want sizing to their
 * content: an id column and a description column given an equal quarter each
 * is the layout those tables were avoiding. This keeps the header, the
 * hairlines and the density, and gives the columns back to the browser.
 */
.pc-grid--auto .table {
	table-layout: auto;
}

.pc-grid thead.table-light {
	--bs-table-bg: var(--pc-surface);
	--bs-table-color: var(--pc-ink-soft);
}

.pc-grid thead > tr > th {
	font: 600 var(--pc-table-head-text) / 1.3 var(--pc-font);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	border-bottom: 1px solid #dfe5ee;
}

/* Rows separated by a hairline rather than by fill, as in the design. */
.pc-grid tbody > tr > td {
	border-top: 1px solid #eef2f7;
	padding-top: 10px;
	padding-bottom: 10px;
}

/*
 * The application id reads as a link, in the tenant's brand colour. Toronto's
 * #165788 on white is 7.63:1; a tenant choosing its own colour is responsible
 * for that colour being legible on white.
 */
.pc-grid .pc-cell-link {
	color: var(--pc-brand);
	text-decoration: none;
	font-weight: 600;
}

.pc-grid .pc-cell-link:hover,
.pc-grid .pc-cell-link:focus-visible {
	text-decoration: underline;
}

/* ======================================================================
 * Filter bar, record count and the auto-refresh switch
 * ====================================================================== */

/* The title with the number of matching applications beside it. */
.pc-page-head {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 12px;
}

.pc-record-count {
	font: 400 var(--pc-text-md) / 1.3 var(--pc-font);
	color: var(--pc-ink-muted);
}

/*
 * Filters read as a row of chips rather than as stacked form rows. Each chip
 * keeps its own label and select so the control stays a real labelled select —
 * keyboard behaviour, screen-reader naming and the existing scripts are all
 * unchanged, only the presentation moves.
 */
.pc-filter-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-bottom: 14px;
}

.pc-filter {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 6px 4px 11px;
	border: 1px solid #dfe5ee;
	border-radius: var(--pc-radius-pill);
	background: var(--pc-surface);
	max-width: 100%;
}

.pc-filter:focus-within {
	border-color: var(--pc-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-brand) 18%, transparent);
}

.pc-filter__label {
	font: 500 var(--pc-text-sm) / 1.2 var(--pc-font);
	color: var(--pc-ink-soft);
	white-space: nowrap;
	margin: 0;
}

/*
 * The select loses its own chrome and borrows the chip's. Kept as a select
 * rather than a custom menu so it stays operable by keyboard and announced as
 * a combobox, which a div-based dropdown would have to reimplement.
 *
 * Matched as a child, not a descendant. The date-range chip hangs an entire
 * panel inside .pc-filter -- a filter-type select, a quick-filter button, a
 * Clear button -- and a descendant match dressed all of them as chip internals:
 * borderless, transparent, 11.5px, and capped at 140px. The cap wrapped
 * "Submitted Time Between" over three lines. The chip's own toggle is a button
 * one level down, so it is named rather than reached by descent.
 */
.pc-filter > .form-select,
.pc-filter > select,
.pc-filter > .dropdown > .form-select {
	border: 0;
	background-color: transparent;
	padding: 2px 26px 2px 4px;
	width: auto;
	/*
	 * A select sizes itself to its longest option, and the permit-type names run
	 * to sixty characters, which made one chip three times the width of the rest.
	 * Capped in px rather than rem so a tenant raising the base size gets larger
	 * text in the same chip instead of a wider chip. Short values — the common
	 * case, "All" or a status — still show in full.
	 */
	max-width: 140px;
	text-overflow: ellipsis;
	font: 500 var(--pc-text-sm) / 1.2 var(--pc-font);
	color: var(--pc-ink);
	box-shadow: none;
}

.pc-filter > .form-select:focus,
.pc-filter > select:focus,
.pc-filter > .dropdown > .form-select:focus {
	box-shadow: none;
	outline: none;
}

/* The date-range picker sits in a chip too, without its own button border --
 * the chip's own control only. The buttons inside its panel are ordinary
 * buttons and keep the borders that say so. */
.pc-filter > .btn,
.pc-filter > .dropdown > .btn {
	border: 0;
	background: transparent;
	padding: 2px 6px;
	font: 500 var(--pc-text-sm) / 1.2 var(--pc-font);
	color: var(--pc-ink);
}

/* One menu surface. ------------------------------------------------------
 *
 * Two kinds of menu were drawn by two different things. Bootstrap's
 * .dropdown-menu is ours to style and was left mostly stock; a <select>'s
 * popup was the operating system's, so the filter chips opened a square,
 * full-bleed, system-blue list that belonged to no design at all.
 *
 * Both are the same component to the person using them, so both are given the
 * same surface here: the tokens, radius, border and selected-row treatment the
 * rest of the interface uses.
 *
 * The selects stay selects. `appearance: base-select` hands the popup to CSS
 * without replacing the control, so keyboard behaviour, the combobox the screen
 * reader announces, form submission and every script already bound to these
 * elements are untouched -- which a div-based menu would have had to
 * reimplement, and which is why they were left native in the first place.
 */

/* Bootstrap's menus, themed through its own custom properties rather than by
 * overriding its rules, so its internals stay its own. */
.dropdown-menu {
	--bs-dropdown-font-size: var(--pc-text-md);
	--bs-dropdown-color: var(--pc-ink);
	--bs-dropdown-bg: var(--pc-surface);
	--bs-dropdown-border-color: var(--pc-border, #dfe5ee);
	--bs-dropdown-border-radius: var(--pc-radius-lg);
	--bs-dropdown-link-color: var(--pc-ink);
	--bs-dropdown-link-hover-bg: var(--pc-surface-muted, #f1f4f9);
	--bs-dropdown-link-hover-color: var(--pc-ink);
	--bs-dropdown-link-active-bg: var(--pc-brand-tint);
	--bs-dropdown-link-active-color: var(--pc-brand-ink);
	--bs-dropdown-item-padding-y: 6px;
	--bs-dropdown-item-padding-x: 12px;
	font-family: var(--pc-font);
	box-shadow: 0 6px 20px rgb(36 44 58 / 12%);
}

/*
 * Pressed and selected are the same state to look at, so they take the same
 * pair -- and they have to be set together.
 *
 * Site.css sets --bs-dropdown-link-active-bg on the *item* for both, which
 * outranks the value the menu above hands down: a custom property declared on
 * the element beats one inherited from its parent, whatever the file order. So
 * the background stayed the old #23527c navy while the text took the brand ink
 * from the menu, and holding the mouse down on an item painted it dark blue on
 * dark blue with the label invisible inside it.
 *
 * Stated on the same selectors rather than on the menu, because that is where
 * the background is being set and the two cannot be allowed to drift apart.
 */
.dropdown-item.active,
.dropdown-item:active {
	--bs-dropdown-link-active-bg: var(--pc-brand-tint);
	--bs-dropdown-link-active-color: var(--pc-brand-ink);
}

/* The two pickers build their own menus. -------------------------------
 *
 * The date range's quick-filter list is made of .dropdown-item and is already
 * carried by the rule above. These two are not, so they are brought across by
 * hand rather than left as the last two menus that look like somewhere else.
 */

/* A panel rather than a list. .shadow-lg is a Bootstrap utility and carries
 * !important, so matching the other menus means saying so at the same weight. */
.datetime-range-dropdown.shadow-lg {
	box-shadow: 0 6px 20px rgb(36 44 58 / 12%) !important;
	border-color: var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
}

/* The time list is built from bare <a>, not .dropdown-item, so none of the
 * --bs-dropdown-link-* values reach it; and its own border and shadow are
 * hard-coded greys that outrank the themed ones. Restated, not overridden
 * piecemeal, because every one of those declarations had to move. */
.timepicker-dropdown {
	padding: 5px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
	box-shadow: 0 6px 20px rgb(36 44 58 / 12%);
}

.timepicker-dropdown a {
	padding: 6px 10px;
	border-radius: var(--pc-radius-sm);
	font: var(--pc-text-md) / var(--pc-leading-body) var(--pc-font);
	color: var(--pc-ink);
}

.timepicker-dropdown a:hover,
.timepicker-dropdown a:focus {
	background-color: var(--pc-surface-muted, #f1f4f9);
	color: var(--pc-ink);
}

/*
 * Hover and selected were both #f0f0f0, so the time already chosen was
 * indistinguishable from the one under the pointer. The selected row takes the
 * tint every other menu here uses for it.
 *
 * The highlight moves to the link: it was on the <li> for .active and on the
 * <a> for aria-selected, which put a grey band behind a tinted row.
 */
.timepicker-dropdown li.active {
	background-color: transparent;
}

.timepicker-dropdown li.active > a,
.timepicker-dropdown li[aria-selected="true"] > a {
	background-color: var(--pc-brand-tint);
	color: var(--pc-brand-ink);
	font-weight: 600;
}

/*
 * Everything below is additive: without support the select keeps the popup it
 * has today, which is the whole reason this is safe to apply site-wide.
 */
@supports (appearance: base-select) and selector(select::picker(select)) {

	/*
	 * Not every select is a popup. `multiple` and `size` greater than one render
	 * as list boxes, and the two plugin-backed selects keep a hidden original
	 * that the plugin -- not the browser -- draws.
	 */
	select:not([multiple]):not([size]),
	select:not([multiple])[size="1"] {
		appearance: base-select;
		/* Bootstrap paints its own chevron as a background image. ::picker-icon
		   draws one now, and two chevrons is one too many. */
		background-image: none;
		/*
		 * base-select makes the button a flex box of two children, the value and
		 * the chevron. Bootstrap's .form-select sets display: block, which wins
		 * and leaves them as two blocks -- so they stack, and the control comes
		 * out twice as tall with the chevron stranded underneath. Restated here
		 * rather than left to the UA sheet, which Bootstrap outranks.
		 */
		display: inline-flex;
		align-items: center;
		flex-wrap: nowrap;
		gap: 6px;
	}

	/*
	 * The value takes the room and the chevron keeps its own. min-width: 0 is
	 * what lets a long value shrink instead of shoving the chevron out; the auto
	 * margin holds the chevron at the right of a full-width control and does
	 * nothing in a chip, which shrink-wraps and has no free space to distribute.
	 */
	select::selectedcontent {
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	select::picker-icon {
		flex: none;
		margin-left: auto;
	}

	.select2-hidden-accessible,
	.multiselect-native-select select {
		appearance: auto;
	}

	/*
	 * The rule that does the work. Setting base-select on the select alone
	 * restyles the closed button and leaves the popup native, which looks more
	 * broken than leaving both alone.
	 */
	select::picker(select) {
		appearance: base-select;
		padding: 5px;
		border: 1px solid var(--pc-border, #dfe5ee);
		border-radius: var(--pc-radius-lg);
		background: var(--pc-surface);
		box-shadow: 0 6px 20px rgb(36 44 58 / 12%);
		font: var(--pc-text-md) / var(--pc-leading-body) var(--pc-font);
		color: var(--pc-ink);
	}

	select::picker-icon {
		color: var(--pc-ink-muted);
		transition: rotate .15s ease;
	}

	select:open::picker-icon {
		rotate: 180deg;
	}

	select option {
		display: flex;
		align-items: center;
		gap: 8px;
		padding: 6px 10px;
		border-radius: var(--pc-radius-sm);
		color: var(--pc-ink);
	}

	/*
	 * Hover and keyboard arrowing are one state to the reader -- the row under
	 * the pointer and the row the arrow keys are on look the same.
	 */
	select option:hover,
	select option:focus {
		background: var(--pc-surface-muted, #f1f4f9);
	}

	select option:checked {
		background: var(--pc-brand-tint);
		color: var(--pc-brand-ink);
		font-weight: 600;
	}

	/*
	 * The tick is the selected row's marker, so it reserves its column on every
	 * row. Left to appear only when checked, each option shifted sideways as the
	 * selection moved down the list.
	 */
	select option::checkmark {
		order: 1;
		margin-left: auto;
		color: var(--pc-brand-ink);
	}

	select option:not(:checked)::checkmark {
		visibility: hidden;
	}

	/*
	 * The chip's 26px of right padding was reserving room for the chevron
	 * Bootstrap painted as a background image. ::picker-icon is a real box that
	 * lays itself out, so that padding became dead space the chip paid for twice.
	 * The 140px cap above it stays: base-select sizes the button to the selected
	 * option rather than the longest, but a selected permit type still runs to
	 * sixty characters.
	 */
	.pc-filter > select {
		gap: 4px;
		padding: 2px 4px;
	}

	/* Options are not confined to the chip's width, so the names the cap
	   truncates are still readable in the list they are chosen from. */
	.pc-filter > select::picker(select) {
		min-width: max-content;
		max-width: min(520px, 90vw);
	}
}

/*
 * Auto refresh. The plugin's green/red ON/OFF pill read as a status rather than
 * a control; this is a plain switch with a text label, which is quieter and
 * says what it does.
 */

/*
 * Body cells may break inside a word: an address with no spaces has to go
 * somewhere. Headers may not — every label fits its column comfortably, so a
 * break there was only ever "APPLICATIO / N", never a necessity.
 */
.pc-grid td {
	overflow-wrap: anywhere;
	word-break: normal;
}

.pc-grid th {
	overflow-wrap: normal;
	word-break: normal;
}

/*
 * bootstrap-table reserves 30px inside each header for the sort arrow, sized
 * for its own default type. Ours is several steps smaller, so that reserve was
 * costing more than the arrow needs and pushing labels into an ellipsis in a
 * column they otherwise fit. Multi-word labels still wrap at the space.
 */
/*
 * Page width. Bootstrap caps .container at 1320px, which left 65px unused on
 * each side of a 1440 screen while the grid was still hiding columns. The
 * design's own shell caps at 1560px, so that is the number used here rather
 * than an invented one.
 *
 * Nothing in the material we hold from Toronto constrains layout width — its
 * tokens cover typeface, text size, text colour and brand colour only — so this
 * is a product decision, not a tenant one.
 *
 * Scoped to pages carrying the data grid rather than applied site-wide. Widening
 * everything also widens prose: paragraphs on the apply page already run to
 * about 138 characters a line at 1320px, well past a comfortable measure, and a
 * 1560px shell took them to 149. A table earns the extra width; a paragraph does
 * not. The prose measure itself is a pre-existing problem and a separate fix.
 */
.container:has(.pc-grid) {
	max-width: 1560px;
}

/*
 * The menu bar takes that width on every page, not only the ones carrying a
 * grid. It is chrome rather than content: what constrains a paragraph has no
 * bearing on a row of menu items, and tying the two together meant the bar had
 * 1320px on most pages and 1560px on a few.
 *
 * That difference was a bug. Labels give way to icons below 1400px of viewport,
 * but the space they actually have is the container — so on a 1440px screen, on
 * a page without a grid, a System Admin account (which carries an extra menu)
 * needed 1414px inside a 1320px box and ran 34px off the side.
 */
nav.navbar .container {
	max-width: 1560px;
}

/*
 * The application form and the details/review page get the wide shell too.
 *
 * They were on Bootstrap's default 1320px with their cards inside
 * .col-sm-10.offset-sm-1, so a third of a 1600px window was margin -- reported as
 * "we can use more space for the application apply and details page". Both are
 * dense, two-column forms rather than prose, so the width is usable.
 *
 * The reason this was avoided before was that widening the shell also widened
 * paragraphs: the note on .container:has(.pc-grid) says the apply page already ran
 * to about 138 characters a line and calls the prose measure "a separate fix".
 * That fix exists now -- main :is(p, li) holds prose to --pc-measure -- so the
 * shell can widen without the text following it.
 */
.container.pc-form {
	max-width: 1560px;
}

/* The centring offset is what the extra width was going into. Scoped to .pc-form
 * so the idiom keeps working everywhere else it is used. */
@media (min-width: 576px) {
	.pc-form > .row > .col-sm-10.offset-sm-1,
	.pc-form > .row > .col-sm-8.offset-sm-2 {
		flex: 0 0 auto;
		width: 100%;
		margin-left: 0;
	}
}

/* ---- Row actions -------------------------------------------------------
 * One control per row rather than a spread of bare icons. Collapsed to a
 * glyph until asked, because on a list this dense the actions are the least
 * often wanted thing in the row.
 */
.pc-grid .pc-chip {
	font-size: var(--pc-table-chip-text);
}

.pc-rowmenu {
	display: flex;
	justify-content: center;
}

.pc-rowmenu__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 1px solid transparent;
	border-radius: var(--pc-radius-sm, 6px);
	background: transparent;
	color: var(--pc-ink-muted, #7a8798);
	line-height: 1;
	cursor: pointer;
}

.pc-rowmenu__toggle:hover,
.pc-rowmenu__toggle[aria-expanded="true"] {
	background: var(--pc-surface-muted, #f1f4f9);
	border-color: var(--pc-border, #dfe5ee);
	color: var(--pc-ink, #242c3a);
}

.pc-rowmenu__toggle:focus-visible {
	outline: 2px solid var(--pc-brand);
	outline-offset: 1px;
}

/* The glyph is drawn rather than typed: a literal ellipsis character is read
 * aloud by some screen readers even inside an aria-hidden span, and three dots
 * of text drift with the tenant font. The button carries the accessible name.
 */
.pc-rowmenu__glyph {
	display: block;
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: currentColor;
	box-shadow: -5px 0 0 currentColor, 5px 0 0 currentColor;
}

.pc-rowmenu__menu {
	--bs-dropdown-min-width: 13rem;
	--bs-dropdown-font-size: var(--pc-table-text);
	--bs-dropdown-border-color: var(--pc-border, #dfe5ee);
	--bs-dropdown-link-hover-bg: var(--pc-surface-muted, #f1f4f9);
	--bs-dropdown-link-active-bg: var(--pc-brand-tint);
	--bs-dropdown-link-active-color: var(--pc-brand-ink);
	box-shadow: 0 6px 20px rgb(36 44 58 / 12%);
}

.pc-rowmenu__item {
	display: flex;
	align-items: center;
	gap: 8px;
	cursor: pointer;
}

.pc-rowmenu__item .bi {
	font-size: 1em;
	opacity: .75;
}

/* Deleting is not undoable, so it does not look like the rest of the menu. */
.pc-rowmenu__item--destructive {
	color: var(--pc-danger, #b42318);
}

.pc-rowmenu__item--destructive:hover,
.pc-rowmenu__item--destructive:focus {
	background: #fdf1f0;
	color: #8f1d13;
}

/* The actions column carries a control, not text, so it should not inherit the
 * cell padding that keeps prose off the rule. */
.pc-grid td:has(> .pc-rowmenu) {
	padding-left: 4px;
	padding-right: 4px;
	overflow: visible;
}

/* ---- Reading measure ---------------------------------------------------
 * A line of prose that runs too long is hard to read: returning to the start
 * of the next line, the eye loses which line that is. Typographic guidance
 * puts a comfortable measure at roughly 45-75 characters. Paragraphs on the
 * apply page ran to 138.
 *
 * Expressed in ch so it follows the tenant. An organization that raises its
 * base size gets larger text on shorter lines, which is the point of raising
 * it; a fixed pixel cap would instead hand them longer lines in bigger type.
 *
 * ch measures the "0" glyph, which is wider than average lowercase, so this
 * sits a little below the character count it looks like.
 */
main :is(p, li) {
	max-width: var(--pc-measure);
}

/* Opt out only where the container dictates the width: a paragraph in a table
 * cell or a menu is laid out by the thing around it, and capping it there would
 * leave the container padded out around a short line.
 *
 * Cards are deliberately not on this list. A card is where prose usually lives —
 * the apply page's guidance sits in one — so exempting cards would have exempted
 * every paragraph this rule exists for.
 *
 * .list-group joins table and .dropdown-menu for the reason given above: a
 * list-group row is a UI row sized by the container around it, not a line of
 * prose. The dashboard builds its unassigned pool from <li>, so every row in it
 * was held to 65ch -- 650px of row inside an 895px card, with the remaining
 * 245px left blank down the right. */
main :is(.pc-grid, table, .dropdown-menu, .list-group) :is(p, li) {
	max-width: none;
}

/* Prose that arrives as a bare run of text rather than as paragraphs. A permit
 * type description is stored as plain text and rendered unwrapped, so there is
 * no element for the rule above to match — the wrapper gives it one. */
.pc-prose {
	max-width: var(--pc-measure);
}

/* ---- Narrow screens ----------------------------------------------------
 * Column widths are fixed pixels, so the grid does not narrow — below about
 * 1300px it runs off the side, taking 300px with it at 1024 and 556px at 768.
 * What is lost is whatever sits rightmost, which is the status.
 *
 * Dropping columns in order of what they are worth puts that choice the right
 * way round. Nothing here is unreachable: the application itself carries every
 * field, and the grid still scrolls.
 *
 * Tier 3 goes first (the organization is often the reader's own, and the
 * application id already identifies the row better than the applicant's name),
 * then the submitted date, then the work window. The id, location, assignee and
 * status stay at every width, because those are what a queue is triaged on.
 */
@media (max-width: 1400px) {
	.pc-grid .pc-col--tier3 {
		display: none;
	}
}

@media (max-width: 1150px) {
	.pc-grid .pc-col--tier2 {
		display: none;
	}
}

@media (max-width: 920px) {
	.pc-grid .pc-col--tier1 {
		display: none;
	}
}

/* ---- Runaway rows ------------------------------------------------------
 * A row is as tall as its longest cell, and one unusually long location took a
 * row to 426px against a median of 109 — four rows' worth of space for one.
 * Clamping the location keeps the list scannable; the full text is on the
 * application, and the title attribute carries it here.
 */
.pc-grid .pc-cell-clamp {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* ---- Export ------------------------------------------------------------
 * The one control on the page still in the old language. Shaped like the
 * filter chips it sits level with, rather than a default Bootstrap button.
 */
.pc-button {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 13px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-pill);
	background: var(--pc-surface);
	font: 500 var(--pc-text-sm) / 1.2 var(--pc-font);
	color: var(--pc-ink);
	cursor: pointer;
}

.pc-button:hover {
	background: var(--pc-surface-muted, #f1f4f9);
	color: var(--pc-ink);
}

.pc-button:focus-visible {
	outline: 0;
	border-color: var(--pc-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-brand) 18%, transparent);
}

/* The one inside the menu commits the export, so it reads as the primary. */
.pc-button--primary {
	background: var(--pc-brand);
	border-color: var(--pc-brand);
	color: #ffffff;
}

.pc-button--primary:hover {
	background: var(--pc-brand);
	color: #ffffff;
	filter: brightness(1.1);
}

/* ---- Menu bar ----------------------------------------------------------
 * The current section is underlined, as the mockups draw it. Nothing marked it
 * before, on any page: a reader arriving through one of eight links had no way
 * to tell which, and a screen reader had no aria-current to announce.
 *
 * The rule is drawn in currentColor so it follows whatever the organization set
 * as its navbar font colour. The design has navy on white; a tenant with a navy
 * bar gets the light inverse from the same line, without configuring anything.
 */
nav.navbar .navbar-nav .nav-link {
	position: relative;
}

/* ::before, not ::after. Bootstrap draws the dropdown caret with
 * .dropdown-toggle::after, and this rule outranks it three classes to one -- so
 * on every /Permit/* page, where the Applications item carries .active, the
 * underline replaced the arrow and the arrow disappeared. It was still there on
 * the dashboard, which is the Home controller and never active. Moving the
 * underline to ::before leaves the caret's pseudo-element alone. */
nav.navbar .navbar-nav .nav-link.active::before {
	content: "";
	position: absolute;
	left: .5rem;
	right: .5rem;
	bottom: 1px;
	height: 2px;
	border-radius: 1px;
	background: currentColor;
}

/* A dropdown toggle keeps room for its caret, so the rule stops short of it
 * rather than running underneath. */
nav.navbar .navbar-nav .nav-link.dropdown-toggle.active::before {
	right: 1.4rem;
}

/* Underlining is not the only signal: it is paired with weight, so the state
 * does not rely on a 2px line alone. */
nav.navbar .navbar-nav .nav-link.active {
	font-weight: 700;
}

/* The current page inside an open menu, marked the same way the list marks a
 * selected chip rather than with a rule it does not have room for. */
nav.navbar .dropdown-item.active,
nav.navbar .dropdown-item.active:focus {
	background: var(--pc-brand-tint);
	color: var(--pc-brand-ink);
	font-weight: 600;
}

/* The search field says what can be searched, so it wants room to show it — but
 * it is the one element in the bar that can give room back. A fixed floor here
 * made it the cause of the overflow instead: everything else in the bar is a
 * label whose width is set by its text, so the search is what has to flex.
 */
nav.navbar #searchDiv {
	flex: 0 1 320px;
	min-width: 150px;
}

/* ---- Sign-in and registration -----------------------------------------
 * A narrow column on a tinted page with the form in a white card, as the
 * mockups draw it. The tint is what makes the card read as a card; on a white
 * page it would just be a bordered rectangle.
 *
 * Nothing here changes what the forms ask for or how they submit.
 */
.pc-auth {
	background: var(--pc-surface-subtle);
	padding: clamp(24px, 6vh, 64px) clamp(16px, 4vw, 48px) 64px;
	min-height: 60vh;

	/* The layout puts every page inside a centred container, so a tint applied
	   here stops at the container edge and reads as a stray panel.
	
	   Painted outside the box rather than laid out wider: a negative margin of
	   50vw overshoots by the width of the scrollbar, which put a horizontal
	   scrollbar on the page. A spread shadow costs no layout, and the clip keeps
	   it to the sides so it does not bleed over the header and footer. */
	box-shadow: 0 0 0 100vmax var(--pc-surface-subtle);
	clip-path: inset(0 -100vmax);
}

.pc-auth__inner {
	width: 100%;
	max-width: 30rem;
	margin: 0 auto;
}

/* Wider where a form has two columns of fields to place. */
.pc-auth__inner--wide {
	max-width: 48rem;
}

.pc-auth__eyebrow {
	display: block;
	margin-bottom: 6px;
	font: 700 var(--pc-table-head-text) / 1.2 var(--pc-font);
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--pc-brand-ink);
}

.pc-auth__title {
	margin: 0 0 6px;
	font: 700 calc(var(--pc-text-base) + 12px) / 1.15 var(--pc-font);
	color: var(--pc-ink);
}

.pc-auth__lede {
	margin: 0 0 20px;
	max-width: var(--pc-measure);
	color: var(--pc-ink-soft);
}

.pc-card {
	background: var(--pc-surface);
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-xl);
	padding: clamp(18px, 3vw, 28px);
	box-shadow: 0 1px 2px rgb(16 24 40 / 6%);
}

.pc-card + .pc-card {
	margin-top: 16px;
}

/* A field: its label above it, its error below, both owned by the field. */
.pc-field + .pc-field {
	margin-top: 16px;
}

.pc-field > label,
.pc-field .form-label {
	display: block;
	margin-bottom: 5px;
	font: 600 var(--pc-text-base) / var(--pc-leading-tight) var(--pc-font);
	color: var(--pc-ink);
}

.pc-auth .form-control,
.pc-auth .form-select {
	border-radius: var(--pc-radius-md);
	border-color: var(--pc-border, #dfe5ee);
}

.pc-auth .form-control:focus,
.pc-auth .form-select:focus {
	border-color: var(--pc-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-brand) 18%, transparent);
}

/* The action that completes the form, at the width of the form. */
.pc-button--block {
	display: flex;
	width: 100%;
	justify-content: center;
	padding: 10px 16px;
	font-weight: 600;
}

.pc-auth__meta {
	margin: 16px 0 0;
	text-align: center;
	color: var(--pc-ink-soft);
}

.pc-auth__rule {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 22px 0 16px;
	color: var(--pc-ink-muted);
	font-size: var(--pc-text-sm);
}

.pc-auth__rule::before,
.pc-auth__rule::after {
	content: "";
	flex: 1 1 auto;
	height: 1px;
	background: var(--pc-border, #dfe5ee);
}

/* Links on the tint take the brand rather than Bootstrap's blue. Two different
 * legacy blues were in use here — #0d6efd and #337ab7 — and both land just under
 * 4.5:1 against this background, which is the tint's doing: on white they scrape
 * past. The brand ink is the one colour in the system already measured against a
 * light surface, and it is what the mockups use for links anyway. */
.pc-auth a:not(.btn):not(.pc-button) {
	color: var(--pc-brand-ink);
}

.pc-auth__links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 18px;
	margin-top: 22px;
	padding-top: 18px;
	border-top: 1px solid var(--pc-border, #dfe5ee);
	font-size: var(--pc-text-sm);
}

/* ---- Page header -------------------------------------------------------
 * The introduction every page in the mockups shares: a small brand eyebrow
 * saying what section you are in, the page title, and a sentence of context.
 *
 * Reused rather than repeated so the pages agree with each other. The lede is
 * held to the reading measure for the same reason the rest of the prose is.
 */
.pc-page-header {
	padding: 4px 0 18px;
	margin-bottom: 18px;
	border-bottom: 1px solid var(--pc-border, #dfe5ee);
}

.pc-page-header__eyebrow {
	display: block;
	margin-bottom: 4px;
	font: 700 var(--pc-table-head-text) / 1.2 var(--pc-font);
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--pc-brand-ink);
}

.pc-page-header__title {
	margin: 0 0 6px;
	font: 700 calc(var(--pc-text-base) + 10px) / 1.15 var(--pc-font);
	color: var(--pc-ink);
}

.pc-page-header__lede {
	margin: 0;
	max-width: var(--pc-measure);
	color: var(--pc-ink-soft);
}

/*
 * A page header that follows you down the page.
 *
 * The application type editor is long enough that its title scrolls away
 * before you are half through it, so Site.css made .permitTypeHeader sticky
 * and -- to separate it from the form behind it -- painted it #23527c with
 * white text. That navy is the product default this work has been taking out
 * of grids and table headers; it was never a tenant's colour.
 *
 * Same behaviour, drawn as the header it is: the page surface, so the text
 * keeps the tenant's ink and the eyebrow keeps the brand, and a shadow rather
 * than a fill to lift it off what scrolls underneath. Declared after Site.css
 * at equal specificity, which is what overrides the fill.
 */
.pc-page-header--sticky {
	position: sticky;
	top: 65px;
	z-index: 1000;
	background: var(--pc-surface);
	color: var(--pc-ink);
	text-align: left;
	margin-bottom: 18px;
	box-shadow: 0 6px 12px -10px rgb(16 24 40 / 45%);
}

/* A permit type, a refund, an organization: the repeated unit on a list page
 * that is not a table. Same card as the forms use, with room to breathe. */
.pc-tile {
	background: var(--pc-surface);
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
	padding: clamp(14px, 2vw, 20px);
}

.pc-tile + .pc-tile {
	margin-top: 14px;
}

.pc-tile__title {
	margin: 0 0 6px;
	font: 700 calc(var(--pc-text-base) + 2px) / 1.25 var(--pc-font);
	color: var(--pc-ink);
}

/* A fee, a duration, a count — a fact about the thing, not a control. */
.pc-facts {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 12px 0;
	padding: 0;
	list-style: none;
}

.pc-fact {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	padding: 4px 10px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-pill);
	background: var(--pc-surface-subtle);
	font-size: var(--pc-text-sm);
	color: var(--pc-ink);
}

.pc-fact__value {
	font-weight: 700;
}

/* ---- Permit types ------------------------------------------------------
 * Choosing what to apply for. An organization can offer a dozen of these, each
 * with a paragraph and a list of fees, and they were one card with rules drawn
 * between them — so the eye had nothing to tell it where one ended.
 *
 * No grouping and no "most common" badge: permit types carry no category and
 * nothing marks one as common. Both are in the mockup and both need a field
 * that does not exist, so neither is invented here.
 */
/* Spacing comes from the cards, not from a flex gap on the list. Each loop
 * iteration wraps its card in a div or two, so the list's children are those
 * wrappers rather than the cards — a gap here left a hole behind every card the
 * filter hid. */
/* The column this page reads in.
 *
 * Prose is capped at a comfortable measure wherever it appears, but the cards
 * here were the full width of the container — so a description stopped just
 * past halfway and left the rest of its own card empty, while the fee chips
 * below it ran the whole way. The text was right; the card was too wide for it.
 *
 * Capping the column instead of widening the text keeps the measure — 138
 * characters a line was the problem this rule was added for — and makes the
 * card edge agree with where the words stop.
 */
.applyPermit > .col-sm-12,
.applyPermit .pc-page-header,
.applyPermit .pc-typelist,
.applyPermit .pc-typefilter {
	max-width: calc(var(--pc-measure) + 3rem);
	margin-inline: auto;
}

.pc-typecard {
	margin-bottom: 16px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
	background: var(--pc-surface);
}

.pc-typecard[hidden] {
	display: none;
}

.pc-typecard .card-body h2,
.pc-typecard .card-body h1 {
	margin: 0 0 8px;
	font-size: var(--pc-text-lg, 1.15rem);
}

/* Fees are a list of structured payment items, so they stay a list for a screen
 * reader and read as chips for everyone else. Ours run longer than the
 * mockup's — "per 50 metre per lane per day" — so they wrap rather than
 * truncate: a fee that has been cut off is worse than a wide one. */
.pc-fees {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 6px 0 0;
	padding: 0;
	list-style: none;
}

.pc-fees > li {
	padding: 4px 12px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-pill);
	background: var(--pc-surface-subtle);
	font-size: var(--pc-text-sm);
	color: var(--pc-ink);
}

.pc-fees__label {
	display: block;
	font-size: var(--pc-table-head-text);
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--pc-ink-muted);
}

.pc-typefilter {
	display: flex;
	align-items: center;
	gap: 16px;
	flex-wrap: wrap;
	margin-bottom: 16px;
}

.pc-typefilter__input {
	flex: 0 1 320px;
	border-radius: var(--pc-radius-pill);
	border-color: var(--pc-border, #dfe5ee);
}

.pc-typefilter__input:focus {
	border-color: var(--pc-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-brand) 18%, transparent);
}

.pc-typefilter__count {
	margin: 0;
	font-size: var(--pc-text-sm);
	color: var(--pc-ink-soft);
}

.pc-typefilter.has-no-matches .pc-typefilter__count {
	font-weight: 600;
	color: var(--pc-ink);
}

/* ---- Application form --------------------------------------------------
 * The longest form in the product: hundreds of fields across a dozen sections.
 *
 * Styled through the sections it already has rather than by rewriting them. The
 * markup is four thousand lines that submit real applications, and the grey
 * header bar on each panel is the only thing between it and the mockup — so the
 * bar goes and the heading stays, which is a stylesheet change rather than a
 * structural one.
 */
.pc-form__header {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

/* The mockup sets the progress opposite the title rather than under it, which
 * keeps the title, the lede and the count each on their own line instead of
 * stacking three things down the left. Only where there is room for two
 * columns; below that it goes back under the lede. */
@media (min-width: 768px) {
	.pc-form__header {
		flex-direction: row;
		align-items: flex-end;
		justify-content: space-between;
		gap: 24px;
		flex-wrap: wrap;
	}

	/* The eyebrow, title and lede are siblings, not a wrapper, so they are held
	 * to the left column by order rather than by nesting. */
	.pc-form__header > .pc-page-header__eyebrow { flex: 0 0 100%; }
	.pc-form__header > .pc-page-header__title  { flex: 1 1 auto; margin-bottom: 0; }
	.pc-form__header > .pc-page-header__lede   { flex: 0 0 100%; order: 3; margin-bottom: 0; }

	.pc-form__header > .pc-form__progress {
		order: 2;
		flex: 0 0 auto;
		margin: 0 0 4px;
	}
}

/* Where the application has got to. Only rendered when it is true, so it never
 * says "Draft" about something already submitted. */
/* The form's required-fields legend. It used to be the page header's lede; page
 * subtitles have been removed, and this is not one -- it tells you how to fill the
 * form in, so it sits with the form and keeps the prose measure. */
.pc-form__legend {
	margin: -6px 0 18px;
	max-width: var(--pc-measure);
	color: var(--pc-ink-soft);
}

.pc-form__status {
	margin-left: 8px;
	padding: 2px 9px;
	border-radius: var(--pc-radius-pill);
	background: #fdf0d9;
	border: 1px solid #e8cfa0;
	color: #6b4500;
	letter-spacing: .04em;
}

/* The application id, beside the word that says what kind of page this is. */
.pc-form__reference {
	margin-left: 8px;
	padding: 2px 8px;
	border-radius: var(--pc-radius-pill);
	background: var(--pc-brand-tint);
	border: 1px solid var(--pc-brand-border);
	color: var(--pc-brand-ink);
	letter-spacing: 0;
	text-transform: none;
}

.pc-required-mark {
	color: var(--pc-danger);
	font-weight: 700;
}

/* A section of the form. The heading sits on the card rather than on a bar
 * across the top of it: a full-width grey strip per section made a dozen of
 * them read as a dozen separate pages. */
.pc-form .card {
	border-radius: var(--pc-radius-lg);
	border-color: var(--pc-border, #dfe5ee);
	box-shadow: 0 1px 2px rgb(16 24 40 / 5%);
}

.pc-form .card + .card,
.pc-form .row + .row > .col-sm-10 > .card {
	margin-top: 14px;
}

.pc-form .card-header {
	background: transparent;
	border-bottom: 1px solid var(--pc-border, #dfe5ee);
	padding: 14px clamp(14px, 2vw, 20px) 12px;
}

.pc-form .card-header h2,
.pc-form .card-header h3 {
	font: 700 calc(var(--pc-text-base) + 2px) / 1.25 var(--pc-font);
	color: var(--pc-ink);
}

.pc-form .card-body {
	padding: clamp(14px, 2vw, 20px);
}

/* Field labels carry the weight; the hint under them does not compete.
 *
 * Weight only, deliberately. Setting a colour here put the tenant's body black
 * on a label sitting inside a navy panel — 2.56:1 — because not every label in
 * this form is on white. Inherited colour was already right everywhere. */
.pc-form label,
.pc-form .form-label {
	font-weight: 600;
	margin-bottom: 4px;
}

.pc-form .form-control,
.pc-form .form-select {
	border-radius: var(--pc-radius-md);
	border-color: var(--pc-border, #dfe5ee);
}

.pc-form .form-control:focus,
.pc-form .form-select:focus {
	border-color: var(--pc-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-brand) 18%, transparent);
}

/* A list of the form's own sections, beside it. Built from what the page
 * rendered, so it is right for every permit type rather than for one. */
.pc-form__progress {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 10px 0 0;
	font: 500 var(--pc-text-sm) / 1.3 var(--pc-font);
	color: var(--pc-ink-soft);
}

.pc-form__bar {
	display: block;
	flex: 0 0 auto;
	width: 160px;
	height: 6px;
	border-radius: var(--pc-radius-pill);
	background: var(--pc-surface-muted, #f1f4f9);
	overflow: hidden;
}

.pc-form__bar-fill {
	display: block;
	height: 100%;
	width: 0;
	border-radius: inherit;
	background: var(--pc-brand);
	transition: width .2s ease-out;
}

.pc-form__progress.is-complete {
	color: #1b6e3c;
	font-weight: 600;
}

.pc-form__progress.is-complete .pc-form__bar-fill {
	background: #1b6e3c;
}

.pc-sections {
	display: none;
}

.pc-sections__heading {
	display: block;
	margin-bottom: 8px;
	font: 700 var(--pc-table-head-text) / 1.2 var(--pc-font);
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--pc-ink-muted);
}

.pc-sections__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Section names come from the form's own headings, and some of them are a
 * sentence. Two lines is enough to tell them apart; the full text stays in the
 * title, along with what is outstanding in that section. */
.pc-sections__link {
	padding: 6px 10px;
	border-left: 2px solid transparent;
	border-radius: 0 var(--pc-radius-sm) var(--pc-radius-sm) 0;
	font-size: var(--pc-text-sm);
	color: var(--pc-ink-soft);
	text-decoration: none;
}

.pc-sections__link:hover {
	background: var(--pc-surface-subtle);
	color: var(--pc-ink);
}

.pc-sections__link.is-current {
	border-left-color: var(--pc-brand);
	background: var(--pc-brand-tint);
	color: var(--pc-brand-ink);
	font-weight: 600;
}

/* Shown only where there is room beside the form. Below that the form already
 * reads top to bottom and a second column would push it narrower. */
@media (min-width: 1200px) {
	/*
	 * Two columns, rather than a float with the content pushed off it.
	 *
	 * The rail was floated and the space beside it made by a margin on
	 * `> .row`. A float takes no space in the block flow, so anything that is
	 * not a `.row` — a card added straight to the form, which is the obvious
	 * thing to add — flowed underneath the rail and covered it. The margin also
	 * repeated the rail's width and gap as one number, 234px, that nothing
	 * checked.
	 *
	 * A grid gives the rail a column of its own. Every child lands in the
	 * second one whatever it is, so there is no list of element types to keep
	 * up to date, and the rail's width is described once.
	 */
	.pc-form--with-sections {
		display: grid;
		grid-template-columns: 210px minmax(0, 1fr);
		column-gap: 24px;
		align-items: start;
	}

	/* Whatever the form contains belongs beside the rail, not under it. */
	.pc-form--with-sections > * {
		grid-column: 2;
		min-width: 0;
	}

	/* The page header names the whole page, so it keeps the full width. */
	.pc-form--with-sections > .pc-form__header {
		grid-column: 1 / -1;
	}

	/*
	 * The rail spans to the end of the grid rather than sitting in one row.
	 * Sticky is bounded by the element's own area, so a rail confined to the
	 * row it was placed in would unstick as soon as that row scrolled past —
	 * which is almost immediately.
	 *
	 * Spanned rather than ended at -1: the rows here are implicit, and -1 names
	 * the last line of the *explicit* grid. With no grid-template-rows that is
	 * line 1, so `2 / -1` normalises to `1 / 2` and the rail took the first row
	 * — putting it above the page header instead of beside the form. The span
	 * is larger than any form this renders.
	 */
	.pc-form--with-sections > .pc-sections {
		display: block;
		grid-column: 1;
		grid-row: 2 / span 500;
		position: sticky;
		top: 90px;
		padding: 14px;
		border: 1px solid var(--pc-border, #dfe5ee);
		border-radius: var(--pc-radius-lg);
		background: var(--pc-surface);
	}
}

/* Where this section sits in the run. The mockup puts a category here; we do
 * not have categories, and a position is true where a category would be made
 * up. */
.pc-section__eyebrow {
	display: block;
	margin-bottom: 2px;
	font: 700 var(--pc-table-head-text) / 1.2 var(--pc-font);
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--pc-ink-muted);
}

/* Not every panel header is white. Three of them carry bg-warning, and the
 * muted grey measured 3.27:1 on that amber — the same mistake as colouring a
 * label without knowing what it sits on. Where the header brings its own
 * background it also brings a text colour that is right for it, so defer. */
.card-header[class*="bg-"] .pc-section__eyebrow,
.card-header[class*="card-heading-"] .pc-section__eyebrow {
	color: inherit;
}

/* The actions are not pinned. ------------------------------------------
 *
 * They were, briefly: on a permit type with every section enabled they sit
 * 7,100px down, so the row carrying Save Draft, Cancel and Apply was made
 * sticky. The agreement checkbox shares that row and came with it.
 *
 * That put "I agree to the terms of use" on screen the moment the form
 * opened, above a form the applicant had not read yet. The consent has to
 * be the last thing, not the first, so the row stays where the markup puts
 * it -- at the end.
 *
 * Pinning the buttons without the checkbox was the other way out, and it
 * trades one problem for another: Apply pinned to the viewport while its
 * gate is off screen fails validation against something the applicant
 * cannot see. The sections rail is how you move around a form this long.
 */

/* A dot per section in the list, filled when nothing in it is outstanding. */
.pc-sections__link {
	display: flex;
	align-items: flex-start;
	gap: 8px;
}

/* Section names come from the form's own headings and some are a sentence.
 * Three lines rather than two: at two, several of these truncated before the
 * word that told them apart. The full text stays in the link's title. */
.pc-sections__text {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.pc-sections__dot {
	flex: 0 0 auto;
	width: 8px;
	height: 8px;
	margin-top: .45em;
	border-radius: 50%;
	border: 1.5px solid var(--pc-ink-muted);
	background: transparent;
}

/* A section with nothing required in it is not "incomplete" — it is just a
 * section, so its dot does not imply outstanding work. */
.pc-sections__link:not(.has-required) .pc-sections__dot {
	border-style: dotted;
	opacity: .55;
}

.pc-sections__link.is-complete .pc-sections__dot {
	border-color: #1b6e3c;
	background: #1b6e3c;
}

/* The form sits on a tint so its sections read as cards rather than as ruled
 * boxes. Painted with a spread shadow for the same reason the sign-in page is:
 * a negative margin of 50vw overshoots by the scrollbar and scrolls the page. */
.pc-form {
	background: var(--pc-surface-subtle);
	padding-top: 4px;
	padding-bottom: 32px;
	box-shadow: 0 0 0 100vmax var(--pc-surface-subtle);
	clip-path: inset(0 -100vmax);
}

/* The page header sits above the tint, on the page itself. */
.pc-form .pc-form__header {
	margin-bottom: 18px;
}

/* A sub-heading inside a section. It was a full-width grey strip, which made
 * every group of fields look like the start of a new section. */
.pc-form .headingLabel {
	background: transparent;
	padding-left: 0;
	padding-right: 0;
	font: 700 calc(var(--pc-text-base) - 1px) / 1.3 var(--pc-font);
	letter-spacing: .02em;
	color: var(--pc-ink);
	border-bottom: 1px solid var(--pc-border, #dfe5ee);
	padding-bottom: 6px;
}

/* ======================================================================
 * The application review
 *
 * The staff view of an application: a summary of the record, the checks that
 * gate a decision, and the decision itself. Sizes derive from --pc-text-base
 * and the tabular cap rather than being written down, so a tenant that raises
 * its body size gets a bigger page rather than a broken one.
 * ====================================================================== */

/* ---- Summary --------------------------------------------------------
 * Label over value, in as many columns as the width allows. A definition
 * list would be the semantic form, but these are rendered as a grid and dl
 * children cannot be grid items without wrappers that defeat the point.
 */
.pc-review-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
	gap: 14px 22px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.pc-review-fact__label {
	display: block;
	margin-bottom: 2px;
	font: 700 var(--pc-table-head-text) / 1.2 var(--pc-font);
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--pc-ink-muted);
}

/* A value long enough to set the height of every fact beside it — an extent
 * naming three streets does — grows downward instead, into the row below it
 * that the grid has already laid out and left empty. */
.pc-review-fact--tall {
	grid-row: span 2;
}

.pc-review-fact__value {
	display: block;
	font: 500 var(--pc-table-text) / 1.45 var(--pc-font);
	color: var(--pc-ink);
}

/* The second line of a fact: the part you only read if the first interests
 * you. Same role as .pc-cell-note in a grid. */
.pc-review-fact__note {
	display: block;
	margin-top: 2px;
	font: 400 var(--pc-table-head-text) / 1.35 var(--pc-font);
	color: var(--pc-ink-muted);
}

/* ---- Readiness ------------------------------------------------------
 * One row per check: a mark that carries its state, what it is, and what to
 * do about it. The mark is not colour alone — each state has its own glyph,
 * because a red circle and a green circle are the same circle to a
 * substantial minority of reviewers.
 */
.pc-checks {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: 0;
	list-style: none;
}

.pc-check {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 13px 0;
	border-top: 1px solid var(--pc-surface-muted);
}

.pc-check:first-child {
	border-top: 0;
	padding-top: 2px;
}

.pc-check__mark {
	flex: none;
	width: 24px;
	height: 24px;
	margin-top: 1px;
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: #e9f7ef;
	color: #1b6e3c;
	border: 1px solid #bfe3cd;
}

.pc-check--warning .pc-check__mark {
	background: #fdf7e6;
	color: var(--pc-warning);
	border-color: #e8d9a8;
}

.pc-check--blocker .pc-check__mark {
	background: #fdf1f0;
	color: var(--pc-danger);
	border-color: #f3c9c4;
}

.pc-check__body {
	flex: 1 1 auto;
	min-width: 0;
}

.pc-check__title {
	display: block;
	font: 600 var(--pc-table-text) / 1.35 var(--pc-font);
	color: var(--pc-ink);
}

.pc-check__detail {
	margin: 2px 0 0;
	font: 400 var(--pc-table-text) / 1.45 var(--pc-font);
	color: var(--pc-ink-muted);
	text-wrap: pretty;
}

.pc-check__action {
	flex: none;
	align-self: center;
}

/* ---- The decision ---------------------------------------------------- */

/* The one-line summary of what readiness found, above the outcomes. Stated
 * again here because the reviewer decides here, and a reason three sections
 * up is a reason they have to go and look for. */
.pc-gate {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	flex-wrap: wrap;
	padding: 11px 14px;
	margin: 0 0 16px;
	border-radius: var(--pc-radius-md);
	background: #fdf1f0;
	border: 1px solid #f3c9c4;
	font: 500 var(--pc-table-text) / 1.45 var(--pc-font);
	color: #8e1d12;
}

.pc-gate > svg {
	flex: none;
	margin-top: 2px;
}

.pc-gate__text {
	flex: 1 1 240px;
	min-width: 0;
}

.pc-gate a {
	color: #8e1d12;
	font-weight: 700;
}

/* The outcomes. A <select> of eight statuses answered "which value" when the
 * question is "what happens to the applicant", so each is now a card that
 * says so, and an unavailable one carries its reason instead of greying out
 * in silence. */
.pc-outcomes {
	border: 0;
	padding: 0;
	margin: 0 0 16px;
	min-width: 0;
}

.pc-outcomes > legend {
	float: left;
	width: 100%;
	padding: 0;
	margin-bottom: 9px;
	font: 700 var(--pc-table-text) / 1.3 var(--pc-font);
	color: var(--pc-ink);
}

.pc-outcomes__grid {
	clear: both;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
	gap: 12px;
}

.pc-outcome {
	display: block;
	padding: 14px;
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
	background: var(--pc-surface);
	cursor: pointer;
	margin: 0;
}

.pc-outcome:hover {
	border-color: var(--pc-brand-border);
	background: var(--pc-surface-subtle);
}

.pc-outcome__top {
	display: flex;
	align-items: center;
	gap: 10px;
}

.pc-outcome input[type="radio"] {
	width: 20px;
	height: 20px;
	flex: none;
	margin: 0;
	accent-color: var(--pc-brand);
}

.pc-outcome__name {
	font: 700 var(--pc-text-md) / 1.25 var(--pc-font);
	color: var(--pc-ink);
}

.pc-outcome__what {
	display: block;
	margin-top: 8px;
	padding-left: 30px;
	font: 400 var(--pc-table-text) / 1.5 var(--pc-font);
	color: var(--pc-ink-muted);
	text-wrap: pretty;
}

.pc-outcome:has(input:checked) {
	border-color: var(--pc-brand);
	background: var(--pc-brand-tint);
	box-shadow: 0 0 0 1px var(--pc-brand);
}

.pc-outcome:has(input:checked) .pc-outcome__what {
	color: var(--pc-ink-strong);
}

/* Dashed, not just faded: an unavailable outcome is a different kind of
 * thing from an unselected one, and opacity alone reads as "not yet clicked". */
.pc-outcome:has(input:disabled) {
	cursor: not-allowed;
	background: var(--pc-surface-muted);
	border-style: dashed;
}

.pc-outcome:has(input:disabled) .pc-outcome__name {
	color: var(--pc-ink-muted);
}

.pc-outcome__blocked {
	position: relative;
	display: block;
	margin-top: 10px;
	padding-left: 30px;
	font: 600 var(--pc-table-text) / 1.45 var(--pc-font);
	color: var(--pc-danger);
	text-wrap: pretty;
}

/* In the same column as the radio, so the reason lines up with the sentence
 * above it rather than starting an indent further in. */
.pc-outcome__blocked > svg {
	position: absolute;
	left: 6px;
	top: 3px;
}

/* Inside a pill there is no room for the sentence, only for the lock that says
 * there is one. The reason travels as the pill's tooltip and as text for a
 * screen reader; readiness states it in full above either way. */
.pc-outcome__blocked--inline {
	position: static;
	display: inline-flex;
	align-items: center;
	margin: 0 0 0 2px;
	padding: 0;
}

.pc-outcome__blocked--inline > svg {
	position: static;
}

/* The statuses that keep the file open. They are not decisions, so they are
 * not cards; they are a row of choices under one label. */
.pc-outcomes--secondary .pc-outcomes__grid {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}

.pc-outcomes--secondary .pc-outcome {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 13px;
	border-radius: var(--pc-radius-pill);
	font: 500 var(--pc-table-text) / 1 var(--pc-font);
	color: var(--pc-ink-strong);
	white-space: nowrap;
}

.pc-outcomes--secondary .pc-outcome:has(input:checked) {
	box-shadow: none;
	color: var(--pc-brand-ink);
	font-weight: 600;
}

.pc-outcomes--secondary .pc-outcome input[type="radio"] {
	width: 17px;
	height: 17px;
}

/* The outcomes inherit the column the select sat in, which was sized for a
 * select: half a row. Three cards of prose stacked into it and left the other
 * half empty. The column that holds them takes the row instead, and what
 * followed it wraps below, which is the reading order anyway — decide, then
 * see when the status last moved. */
.row > [class*="col-"]:has(.pc-outcomes) {
	flex: 0 0 100%;
	max-width: 100%;
}

/* A grouped part of the decision — the notification, and anything an outcome
 * asks for. Nested in the decision rather than beside it, because the notice
 * is part of the decision and a separate card said it was a separate act. */
.pc-panel {
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-lg);
	overflow: hidden;
	margin-bottom: 14px;
}

.pc-panel:last-child {
	margin-bottom: 0;
}

.pc-panel__head {
	padding: 13px 15px;
	background: var(--pc-surface-sunken);
	border-bottom: 1px solid var(--pc-border, #dfe5ee);
	display: flex;
	align-items: center;
	gap: 10px 14px;
	flex-wrap: wrap;
}

.pc-panel__title {
	flex: 1 1 auto;
	min-width: 0;
	margin: 0;
	font: 700 var(--pc-table-text) / 1.3 var(--pc-font);
	color: var(--pc-ink);
}

.pc-panel__body {
	padding: 15px;
}

/* The select the outcomes are built from stays in the form and keeps posting;
 * it is only hidden once its replacement exists. Without the script it is
 * still the control, which is why this is applied by the script and not here. */
.pc-decision__native.is-replaced {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

/* ======================================================================
 * Buttons
 *
 * Four families carry the product: btn-default (246 uses), btn-success (111),
 * btn-danger (67) and btn-primary (11). They were defined in Site.css, where
 * btn-default was not defined at all — it is a Bootstrap 3 class that
 * Bootstrap 5 dropped, so a quarter of the buttons in the product were
 * rendering as bare Bootstrap base with a hover colour borrowed from the nav.
 *
 * Moved here so they are built from the tenant's tokens rather than from three
 * hard-coded hexes, and so one file owns them.
 *
 * The class names are left alone. Renaming 435 call sites to say what each
 * button means rather than what colour it is would be the better change and a
 * far larger one; this makes them look right first.
 * ====================================================================== */

.btn-default,
.btn-success,
.btn-primary,
.btn-danger {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	min-height: 38px;
	padding: 8px 16px;
	border: 1px solid transparent;
	border-radius: var(--pc-radius-lg);
	font: 600 var(--pc-table-text) / 1.2 var(--pc-font);
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
}

/* The ordinary button, and the one that was not styled: the tenant's brand as
 * an outline, not as a fill, so a toolbar of six of them does not read as six
 * primary actions. */
.btn-default {
	background: var(--pc-surface);
	border-color: var(--pc-brand-border);
	color: var(--pc-brand-ink);
}

.btn-default:hover,
.btn-default:active,
.btn-default:active:hover {
	background: var(--pc-surface-subtle);
	border-color: var(--pc-brand);
	color: var(--pc-brand-ink);
}

/*
 * The action that completes the page. Filled with the brand rather than the
 * old fixed green: on a page that is otherwise the tenant's colour, a green
 * submit button belonged to a different product.
 *
 * The text colour is derived on the server, not set to white here. White on a
 * mid-yellow brand is a button nobody can read, and CSS cannot ask how light a
 * colour is — see BrandPalette.OnBrand.
 */
.btn-success,
.btn-primary {
	background: var(--pc-brand);
	border-color: var(--pc-brand);
	color: var(--pc-on-brand);
	font-weight: 700;
}

.btn-success:hover,
.btn-primary:hover,
.btn-success:active,
.btn-primary:active,
.btn-success:active:hover,
.btn-primary:active:hover {
	background: color-mix(in srgb, var(--pc-brand) 86%, #000);
	border-color: color-mix(in srgb, var(--pc-brand) 86%, #000);
	color: var(--pc-on-brand);
}

/* Destructive, and deliberately not the brand: cancelling an application means
 * the same thing whichever organization is looking at it. */
.btn-danger {
	background: var(--pc-danger);
	border-color: var(--pc-danger);
	color: #fff;
	font-weight: 700;
}

.btn-danger:hover,
.btn-danger:active,
.btn-danger:active:hover {
	background: #8e1d12;
	border-color: #8e1d12;
	color: #fff;
}

/* One focus ring for all four, and a visible one. The rules these replace used
 * -webkit-focus-ring-color, which draws nothing in Firefox. */
.btn-default:focus-visible,
.btn-success:focus-visible,
.btn-primary:focus-visible,
.btn-danger:focus-visible {
	outline: 3px solid var(--pc-brand);
	outline-offset: 2px;
	box-shadow: none;
}

.btn-default:disabled,
.btn-success:disabled,
.btn-primary:disabled,
.btn-danger:disabled,
.btn-default.disabled,
.btn-success.disabled,
.btn-primary.disabled,
.btn-danger.disabled {
	opacity: .5;
	cursor: not-allowed;
}

/* A button in a dense place — a grid row, a toolbar above a table — is the same
 * button at the size that context can afford. */
.btn-sm.btn-default,
.btn-sm.btn-success,
.btn-sm.btn-primary,
.btn-sm.btn-danger,
.pc-grid .btn-default,
.pc-grid .btn-success,
.pc-grid .btn-primary,
.pc-grid .btn-danger {
	min-height: 30px;
	padding: 4px 11px;
	border-radius: var(--pc-radius-md);
	font-size: var(--pc-table-head-text);
}

/* Bootstrap's own full-width helper has to keep working on all four. */
.btn-default.smallScreenFullWidth,
.btn-success.smallScreenFullWidth,
.btn-primary.smallScreenFullWidth,
.btn-danger.smallScreenFullWidth {
	max-width: 100%;
}

/*
 * The families Bootstrap supplied and nobody chose.
 *
 * btn-outline-secondary, btn-info, btn-outline-primary and btn-secondary are
 * spread across the payment, scheduled-report and two-factor screens, and they
 * render in Bootstrap's grey and cyan -- beside a btn-default in the tenant's
 * brand, on the same toolbar. None of them is making a point that btn-default
 * is not already making, so they are drawn as it is: the quiet outline, the
 * same height, the same radius.
 *
 * Listed separately from the four above rather than folded into that selector
 * so the block stays readable as what it is -- an alias list, not a fifth
 * decision about what a button means.
 */
.btn-secondary,
.btn-info,
.btn-outline-secondary,
.btn-outline-primary,
.btn-outline-danger,
.btn-warning {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	min-height: 38px;
	padding: 8px 16px;
	border: 1px solid transparent;
	border-radius: var(--pc-radius-lg);
	font: 600 var(--pc-table-text) / 1.2 var(--pc-font);
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
}

.btn-secondary,
.btn-info,
.btn-outline-secondary,
.btn-outline-primary {
	background: var(--pc-surface);
	border-color: var(--pc-brand-border);
	color: var(--pc-brand-ink);
}

.btn-secondary:hover,
.btn-info:hover,
.btn-outline-secondary:hover,
.btn-outline-primary:hover {
	background: var(--pc-brand-tint);
	border-color: var(--pc-brand);
	color: var(--pc-brand-ink);
}

/* Destructive, said quietly -- these are the row-level deletes, not the button
   that cancels an application. */
.btn-outline-danger {
	background: var(--pc-surface);
	border-color: var(--pc-danger);
	color: var(--pc-danger);
}

.btn-outline-danger:hover {
	background: var(--pc-danger);
	color: #fff;
}

/* The one that is genuinely saying "careful". Amber rather than the brand,
   for the same reason btn-danger is not the brand: it means the same thing
   whichever organization is looking at it. */
.btn-warning {
	background: #f0ad4e;
	border-color: #eb9316;
	color: #23241f;
	font-weight: 700;
}

.btn-warning:hover {
	background: #eb9316;
	border-color: #d58512;
	color: #23241f;
}

.btn-secondary:focus-visible,
.btn-info:focus-visible,
.btn-outline-secondary:focus-visible,
.btn-outline-primary:focus-visible,
.btn-outline-danger:focus-visible,
.btn-warning:focus-visible {
	outline: 3px solid var(--pc-brand);
	outline-offset: 2px;
	box-shadow: none;
}

/* Same density step the other four take in a grid or a toolbar. */
.btn-sm.btn-secondary,
.btn-sm.btn-info,
.btn-sm.btn-outline-secondary,
.btn-sm.btn-outline-primary,
.btn-sm.btn-outline-danger,
.btn-sm.btn-warning,
.pc-grid .btn-secondary,
.pc-grid .btn-info,
.pc-grid .btn-outline-secondary,
.pc-grid .btn-outline-primary,
.pc-grid .btn-outline-danger,
.pc-grid .btn-warning {
	min-height: 30px;
	padding: 4px 11px;
	border-radius: var(--pc-radius-md);
	font-size: var(--pc-table-head-text);
}

/* ======================================================================
 * Tables on an application
 *
 * The application page carries twenty-odd tables — payments, the field
 * values, drawings, the communication log, consultation, comments — and they
 * were Bootstrap's defaults over Site.css's: a navy header, rows banded in
 * #D1EBFF, and a full border grid where the markup said table-bordered. Three
 * different treatments on one page, none of them the one the application list
 * already uses.
 *
 * They read as the grid does now: a quiet white header, hairline rules between
 * rows, no banding. Scoped to .pc-form so the 47 other views that depend on
 * .table-light and .table-striped are untouched.
 *
 * The lane-pattern tables are not caught by this. They carry .laneTable and
 * .laneApproachTable and no .table, and they are a diagram rather than a list —
 * fixed layout, sprite icons, their own spacing in LaneSprites.css.
 * ====================================================================== */

.pc-form .table {
	font-size: var(--pc-table-text);
	color: var(--pc-ink);
	--bs-table-bg: transparent;
	--bs-table-color: var(--pc-ink);
	--bs-table-striped-bg: transparent;
	--bs-table-striped-color: var(--pc-ink);
	--bs-table-hover-bg: var(--pc-surface-subtle);
	--bs-table-hover-color: var(--pc-ink);
	--bs-table-accent-bg: transparent;
	border-color: var(--pc-border, #dfe5ee);
	margin-bottom: 0;
}

/*
 * The header names the columns; it is not a band of colour across the page.
 *
 * Bootstrap paints table backgrounds through --bs-table-bg and an inset
 * box-shadow rather than background-color, so a thead carrying .table-light
 * kept Site.css's navy until both were overridden — the same thing the grid
 * had to do.
 */
.pc-form .table > thead,
.pc-form .table > thead.table-light {
	--bs-table-bg: var(--pc-surface-sunken);
	--bs-table-color: var(--pc-ink-muted);
	--bs-table-accent-bg: transparent;
}

.pc-form .table > thead > tr > th,
.pc-form .table > thead > tr > td {
	box-shadow: none;
	background: var(--pc-surface-sunken);
	color: var(--pc-ink-muted);
	font: 600 var(--pc-table-head-text) / 1.3 var(--pc-font);
	letter-spacing: .04em;
	text-transform: uppercase;
	text-align: left;
	vertical-align: bottom;
	border-bottom: 1px solid var(--pc-border, #dfe5ee);
	padding: 10px 12px;
}

.pc-form .table > tbody > tr > td,
.pc-form .table > tbody > tr > th {
	padding: 10px 12px;
	vertical-align: top;
	border-top: 1px solid #eef2f7;
	border-bottom: 0;
	box-shadow: none;
}

.pc-form .table > tbody > tr:first-child > td,
.pc-form .table > tbody > tr:first-child > th {
	border-top: 0;
}

/*
 * table-bordered drew a box around every cell, which on a page of label/value
 * rows is a grid of 200 boxes. The rules that separate rows are enough; the
 * columns are separated by the gap between a label and its value.
 */
.pc-form .table-bordered > :not(caption) > * {
	border-width: 0;
}

.pc-form .table-bordered > :not(caption) > * > * {
	border-width: 0;
}

/* The label column of a detail row: quiet, and not competing with its value. */
.pc-form .table .permitDetailLabel {
	width: 34%;
	font-weight: 600;
	color: var(--pc-ink-strong);
}

/* A table that has to scroll sideways says so with an edge, rather than the
 * last column simply stopping. */
.pc-form .table-responsive {
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-md);
}

.pc-form .table-responsive > .table {
	margin-bottom: 0;
}

/* A nested table — the contact blocks inside a field value — is part of its
 * row, not a second list, so it loses the header treatment and the outer rule. */
.pc-form .table .table {
	background: transparent;
	font-size: inherit;
}

.pc-form .table .table > tbody > tr > td {
	padding: 6px 10px;
}

/* A section heading that also answers its own question — "Assigned staff" and
 * who. The name was a row underneath repeating the words above it. */
.pc-section__who {
	font: 400 var(--pc-text-md) / 1.3 var(--pc-font);
	color: var(--pc-ink-soft);
}

.pc-section__who::before {
	content: " — ";
	color: var(--pc-ink-faint, #c3cbd9);
}

/* ======================================================================
 * The location on an application
 * ====================================================================== */

/*
 * The map keeps pace with the traffic impact beside it.
 *
 * The map is 40vh and the impact panel beside it runs to about 1,800px, so
 * two thirds of the map's column was blank and the map itself had scrolled
 * away by the time a reviewer reached the segment it belonged to — which is
 * the one moment the two are read together.
 */
@media (min-width: 992px) {
	#locationInfo > .col-md-6:first-of-type {
		position: sticky;
		top: 90px;
		align-self: flex-start;
	}
}

/*
 * The controls above the map sat on one line each because both the label and
 * the select carry Bootstrap's float-end, which takes them out of the flow
 * separately. Overriding a utility needs !important; the alternative is
 * editing the markup of a control that four other permit types also render.
 */
#locationInfo label[for="showM511Data"],
#locationInfo #showM511Data {
	float: none !important;
}

#locationInfo .col-sm-8:has(#showM511Data) {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 10px;
	flex-wrap: wrap;
}

#locationInfo label[for="showM511Data"] {
	margin: 0;
	white-space: nowrap;
	font: 600 var(--pc-table-text) / 1.3 var(--pc-font);
	color: var(--pc-ink-strong);
}

#locationInfo #showM511Data {
	width: auto;
	min-width: 15rem;
	max-width: 100%;
}

/* The map's own frame, matching the cards around it rather than the browser
 * default border it had. */
.pc-form .permit-application-change-map-canvas {
	border: 1px solid var(--pc-border, #dfe5ee);
	border-radius: var(--pc-radius-md);
	height: 46vh;
	max-height: 520px;
}

/* Route notes and the traffic impact are headings inside a section, not
 * sections of their own — they were the same size as the section title. */
#locationCommentsDiv > h2,
.pc-form h2.headingLabel {
	font: 700 var(--pc-text-lg) / 1.3 var(--pc-font);
	color: var(--pc-ink);
}

/*
 * The lane diagram is a fixed-layout table, so a long impact note in the
 * second column was pushed hard against the right edge and read as though it
 * belonged to nothing. It reads from the left like the rest of the panel.
 */
.laneApproachTable td,
.laneTable > tbody > tr > td {
	text-align: left;
	vertical-align: middle;
}

.laneApproachTable {
	border-color: var(--pc-border, #dfe5ee) !important;
	border-radius: var(--pc-radius-sm);
}

/* ======================================================================
 * THE LANE DIAGRAM, DRAWN AS A ROAD
 *
 * The lane icons were a convention a reviewer had to know: the rightmost
 * sprite is the curb lane, a sidewalk sprite among them is the walk. Lane
 * order and the right anchor are the product's and are unchanged — what is
 * added is the road around them. A centre line the lanes run from, a kerb
 * they run to, and the walk beyond it, so the convention is shown rather
 * than remembered.
 *
 * The strip hugs its lanes, so the centre line sits against the leftmost
 * one rather than a column away. Every row is still anchored to the same
 * right edge, which is what makes a two-lane and a three-lane road
 * comparable down the page.
 *
 * The sprites are NOT resized here. LaneSprites.css owns their dimensions
 * and they break if that changes.
 * ====================================================================== */

.laneRoad {
	display: inline-flex;
	align-items: stretch;
	background: #e9edf2;
	border-radius: var(--pc-radius-sm, 5px);
	overflow: hidden;
	min-height: 44px;
	white-space: nowrap;
}

/*
 * The road anchors to the right edge of its cell -- that shared edge is what
 * makes a two-lane and a three-lane row comparable down the page. The cell is
 * left-aligned a few rules above by `.laneApproachTable td`, so this has to
 * match that specificity to win.
 */
td.lanePatternColumn {
	text-align: right;
}

/* The lanes keep their own sizing; inside the road they only stop stretching. */
.laneRoad .lanePatternColumnDiv {
	align-items: center;
	padding: 5px 2px;
}

.laneRoad__centre {
	flex: none;
	width: 6px;
	background: repeating-linear-gradient(to bottom, #e8b923 0 9px, transparent 9px 18px);
}

.laneRoad__kerb {
	flex: none;
	width: 7px;
	background: repeating-linear-gradient(to bottom, #9aa5b5 0 8px, #cfd6df 8px 16px);
}

/*
 * The walk. A closed sidewalk sprite only said that something changed; the
 * band says what pedestrians get instead, in the product's own words.
 */
.laneRoad__walk {
	flex: none;
	width: 88px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 5px;
	background: #dfe5ec;
	font-size: 10.5px;
	font-weight: 600;
	line-height: 1.25;
	letter-spacing: .02em;
	text-transform: uppercase;
	text-align: center;
	/* Wrap between the words, never inside one: "PRO TECTED PATH" is not a label. */
	white-space: normal;
	word-break: normal;
	overflow-wrap: normal;
	hyphens: none;
	color: #59637a;
}

.laneRoad__walk.is-protected {
	background: #e9f7ef;
	color: #1b6e3c;
}

.laneRoad__walk.is-detour {
	background: #fdf7e6;
	color: #7a5a00;
}

.laneRoad__walk.is-closed {
	background: #fdf1f0;
	color: #b42318;
}

/* A whole-road closure has no lanes to draw. */
.laneRoadClosed {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 14px;
	border-radius: var(--pc-radius-sm, 5px);
	background: #fdf1f0;
	color: #b42318;
	font-weight: 600;
}

/*
 * The sentence. Built from the same pattern string the icons are, so the two
 * cannot disagree — and a screen reader gets the closure in words rather than
 * a list of image titles.
 */
.laneSays {
	margin: 6px 0 0;
	line-height: 1.5;
	text-align: left;
	white-space: normal;
	color: var(--pc-ink-strong, #333d4d);
}

.laneSays b {
	font-weight: 700;
}

.laneChips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 7px;
	justify-content: flex-start;
	white-space: normal;
}

.laneChip {
	display: inline-flex;
	align-items: center;
	padding: 4px 10px;
	border: 1px solid var(--pc-brand-border, #d5e1ea);
	border-radius: var(--pc-radius-pill, 999px);
	background: var(--pc-brand-tint, #ecf2f5);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--pc-brand-ink, #165788);
	white-space: nowrap;
}

/* Only the colour is added to the product's own wording, so which provision is
 * the weaker one reads at a glance down a long list. */
.laneChip--ok {
	background: #e9f7ef;
	border-color: #bfe3cd;
	color: #1b6e3c;
}

.laneChip--warn {
	background: #fdf7e6;
	border-color: #e8d9a8;
	color: #7a5a00;
}

.laneChip--merge {
	background: #fff4ed;
	border-color: #f6d3bd;
	color: #9a3412;
}

.laneChip--quiet {
	background: var(--pc-surface-muted, #f1f4f9);
	border-color: #dbe2ec;
	color: #4d5768;
}

.laneRoadNameColumn {
	vertical-align: middle !important;
}

.laneRoadNameColumn__count {
	display: block;
	margin-top: 2px;
	font-size: 11.5px;
	font-style: normal;
	font-weight: 400;
	color: var(--pc-ink-muted, #606c7b);
}

/*
 * The row was 32px for a single strip of sprites. It now carries the road, the
 * sentence and the provisions, so it takes the height it needs and the rows are
 * told apart by a hairline instead of a box.
 */
.laneApproachTable .laneRow {
	height: auto;
}

.laneApproachTable > tbody > tr + tr > td,
.laneApproachTable > tr + tr > td {
	border-top: 1px solid var(--pc-border, #e4e8ef);
}

.laneApproachTable td {
	padding: 9px 6px;
}

@media screen and (max-width: 640px) {
	/* The walk label is the first thing to give up its width. */
	.laneRoad__walk {
		width: 62px;
		font-size: 9.5px;
	}
}

/* ======================================================================
 * SEGMENTS, AND THE FEE
 *
 * A reviewer read "Woodbine Ave at Sammon Ave to 41 m North of Springdale
 * Blvd" and then had to find that road on the map by its name. The segments
 * are numbered instead, and the map carries the same numbers, so a route
 * note or a possible conflict can point at one.
 *
 * The fee was a sentence -- rate, segments, lanes, days, tax and total on
 * one line. That is the working, not the answer; the amount leads and the
 * working is a disclosure under it.
 * ====================================================================== */

.laneSegment > td {
	padding-top: 14px !important;
}

.laneSegment__pin {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 26px;
	height: 26px;
	margin-right: 9px;
	border-radius: 50%;
	background: var(--pc-brand, #165788);
	color: var(--pc-on-brand, #fff);
	font-size: var(--pc-table-text, 15px);
	font-weight: 700;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	vertical-align: middle;
}

.laneLocationDescSpan {
	vertical-align: middle;
}

.laneFeeRow {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 10px;
	margin-top: 8px;
	padding: 11px 13px !important;
	border: 1px solid var(--pc-brand-border, #d5e1ea);
	border-radius: var(--pc-radius-md, 7px);
	background: var(--pc-brand-tint, #ecf2f5);
}

/* The running total for the whole application, not one segment's fee. */
.laneFeeRow--total {
	margin-top: 16px;
	border-width: 2px;
	font-size: var(--pc-text-md, 17.5px);
	font-weight: 600;
	color: var(--pc-brand-ink, #165788);
}

.laneFee__label {
	font-weight: 600;
	color: var(--pc-brand-ink, #165788);
}

.laneFee__amount {
	margin-left: auto;
	font-size: var(--pc-text-xl, 21px);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--pc-brand-ink, #165788);
}

.laneFee__calc {
	flex: 1 1 100%;
}

.laneFee__calc summary {
	cursor: pointer;
	font-size: var(--pc-table-head-text, 12px);
	font-weight: 500;
	color: var(--pc-brand-ink, #165788);
	list-style: none;
}

.laneFee__calc summary::-webkit-details-marker {
	display: none;
}

.laneFee__calc summary::before {
	content: "\25B8\00A0";
	color: var(--pc-ink-muted, #606c7b);
}

.laneFee__calc[open] summary::before {
	content: "\25BE\00A0";
}

.laneFee__calc p {
	margin: 6px 0 0;
	padding: 9px 11px;
	border-radius: var(--pc-radius-sm, 5px);
	background: #fff;
	font-size: var(--pc-table-text, 15px);
	font-variant-numeric: tabular-nums;
	white-space: normal;
	color: var(--pc-ink-strong, #333d4d);
}

/*
 * The view and download icons beside a file. They were 19x18 and 15x18 — named
 * for a screen reader, but under the 24px WCAG 2.2 asks of a target, and a row
 * carries several of them a few pixels apart.
 */
.pc-form a:has(> .bi-eye),
.pc-form a:has(> .bi-download),
.pc-form a:has(> .bi-trash) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 26px;
	min-height: 26px;
	border-radius: var(--pc-radius-sm);
	vertical-align: middle;
}

.pc-form a:has(> .bi-eye):hover,
.pc-form a:has(> .bi-download):hover,
.pc-form a:has(> .bi-trash):hover {
	background: var(--pc-brand-tint);
}

/*
 * The view and download icons beside a file. They were 19x18 and 15x18 — named
 * for a screen reader, but under the 24px WCAG 2.2 asks of a target, and a row
 * carries several of them a few pixels apart.
 */
.pc-form a:has(> .bi-eye),
.pc-form a:has(> .bi-download),
.pc-form a:has(> .bi-trash) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 26px;
	min-height: 26px;
	border-radius: var(--pc-radius-sm);
	vertical-align: middle;
}

.pc-form a:has(> .bi-eye):hover,
.pc-form a:has(> .bi-download):hover,
.pc-form a:has(> .bi-trash):hover {
	background: var(--pc-brand-tint);
}

/*
 * Possible conflicts. The panel is revealed by the conflict check when it finds
 * something, and its heading was .text-white on a white card -- invisible, so
 * the table arrived with no name above it.
 */
.pc-conflicts {
	margin-top: 18px;
	padding: 14px 16px;
	border: 1px solid var(--pc-border, #e4e8ef);
	border-left: 3px solid #d9a441;
	border-radius: var(--pc-radius-md, 7px);
	background: var(--pc-surface-sunken, #f4f7fc);
}

.pc-conflicts__heading {
	margin: 0;
	font-size: var(--pc-text-lg, 18.5px);
	font-weight: 700;
	color: var(--pc-ink, #000);
}

.pc-conflicts__note {
	margin: 4px 0 12px;
	font-size: var(--pc-table-text, 15px);
	color: var(--pc-ink-muted, #606c7b);
}

.pc-conflicts .table {
	margin-bottom: 0;
	background: #fff;
}
