/*
 * Component layer.
 *
 * Each block below ports one design-system component from its React source in
 * components/ — the values are the component's values, not approximations. Where a
 * comment cites a source file, that file is the reference if anything here drifts.
 *
 * Naming: .lb-block, .lb-block__element, .lb-block--modifier.
 */

/* -------------------------------------------------------------------------
 * Icon — core/Icon.jsx
 * ---------------------------------------------------------------------- */

.lb-icon {
  display: block;
  flex: none;
}

/* -------------------------------------------------------------------------
 * Button — core/Button.jsx
 *
 * Hover darkens, never lightens. Press reuses the hover colour with no scale
 * change: nothing in this system bounces or shrinks.
 * ---------------------------------------------------------------------- */

.lb-chrome .lb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding: 0 var(--space-5);
  font-family: var(--font-body);
  font-size: var(--text-small);
  /* The source sets line-height 1; Bangla ascenders need a little more room and the
     flex centring makes the box identical either way. */
  line-height: 1.2;
  font-weight: var(--weight-semibold);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background var(--dur-base) var(--ease-standard),
    color var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard);
}

.lb-chrome .lb-btn:hover {
  text-decoration: none;
}

/*
 * Scoped with .lb-chrome for the same reason the base rule is: without it these read
 * as 0,1,0 against the base's 0,2,0 and lose every tie, so `lg` and `sm` silently did
 * nothing and every large button on the site rendered at the default 44px/14px.
 */
.lb-chrome .lb-btn--sm {
  min-height: var(--control-height-sm);
  padding: 0 var(--space-4);
  font-size: var(--text-caption);
}

.lb-chrome .lb-btn--lg {
  min-height: 52px;
  padding: 0 var(--space-6);
  font-size: var(--text-body-size);
}

.lb-btn--full {
  width: 100%;
}

.lb-chrome .lb-btn--primary {
  background: var(--action-primary);
  color: var(--white);
}

.lb-chrome .lb-btn--primary:hover {
  background: var(--action-primary-hover);
  color: var(--white);
}

.lb-chrome .lb-btn--secondary {
  background: transparent;
  color: var(--deep-green);
  border-color: var(--deep-green);
}

.lb-chrome .lb-btn--secondary:hover {
  background: var(--green-tint-6);
  color: var(--deep-green);
}

.lb-chrome .lb-btn--tertiary {
  background: transparent;
  color: var(--deep-green);
  padding: 0 var(--space-1);
}

.lb-chrome .lb-btn--tertiary:hover {
  color: var(--forest);
  text-decoration: underline;
}

/* Amber fill with Ink text — reserve for the single most important action on a page.
   Never white text on amber. */
.lb-chrome .lb-btn--accent {
  background: var(--action-accent);
  color: var(--text-on-amber);
}

.lb-chrome .lb-btn--accent:hover {
  background: var(--action-accent-hover);
  color: var(--text-on-amber);
}

.lb-chrome .lb-btn--accent:focus-visible {
  box-shadow: var(--ring-focus-amber);
}

/* Outlined button on a Forest or Deep Green band. */
.lb-chrome .lb-btn--ghost {
  background: transparent;
  color: var(--white);
  border-color: var(--ghost-border-on-dark);
}

.lb-chrome .lb-btn--ghost:hover {
  background: var(--wash-on-dark);
  border-color: var(--ghost-border-on-dark-hover);
  color: var(--white);
}

/* A ghost only ever lives on a Forest or Deep Green band, where the system's
   Deep Green ring disappears into the surface. The ring switches to white for
   this variant — the same per-variant move the accent button makes for amber. */
.lb-chrome .lb-btn--ghost:focus-visible {
  box-shadow: 0 0 0 var(--focus-width) var(--white);
}

.lb-chrome .lb-btn:disabled,
.lb-chrome .lb-btn[aria-disabled="true"] {
  opacity: .4;
  pointer-events: none;
}

/* -------------------------------------------------------------------------
 * Field — forms/Input.jsx and forms/Select.jsx
 *
 * :focus-within replaces the component's focus state. It also sidesteps the trap
 * recorded in context.md: spreading onBlur onto the React Input killed the internal
 * handler and left fields stuck in focus. CSS has no such failure mode.
 * ---------------------------------------------------------------------- */

.lb-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2);
  min-width: 0;
  font-family: var(--font-body);
}

.lb-field__label {
  font-size: var(--text-small);
  /* Fixed, not `normal`: a label holding Latin glyphs (the parentheses in মাপ (সেমি))
     otherwise gets a taller line box than a pure-Bangla one (ওজন), and every control
     below it drifts out of the row. One line-height, one row. */
  line-height: var(--lh-small);
  font-weight: var(--weight-medium);
  color: var(--ink);
}

.lb-field__control {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-height);
  padding: 0 var(--space-3);
  background: var(--surface-raised);
  border: var(--border-width) solid var(--border-field);
  border-radius: var(--radius-md);
  transition:
    border-color var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}

.lb-field__control:focus-within {
  border-color: var(--deep-green);
  box-shadow: var(--ring-focus);
}

.lb-chrome .lb-field__control input,
.lb-chrome .lb-field__control select,
.lb-chrome .lb-field__control textarea {
  flex: 1;
  min-width: 0;
  height: auto;
  margin: 0;
  padding: 0;
  border: none;
  outline: none;
  box-shadow: none;
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--text-body-size);
  font-weight: var(--weight-regular);
  line-height: 1.2;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.lb-chrome .lb-field__control input:focus,
.lb-chrome .lb-field__control select:focus {
  box-shadow: none;
  outline: none;
}

.lb-field__control .lb-icon {
  color: var(--muted);
}

.lb-field__suffix {
  font-size: var(--text-small);
  color: var(--muted);
  white-space: nowrap;
}

.lb-field__hint {
  font-size: var(--text-caption);
  line-height: var(--lh-caption);
  color: var(--muted);
}

/* Errors use Delayed red on the border and the message. */
.lb-field--error .lb-field__control {
  border-color: var(--status-delayed);
}

.lb-field--error .lb-field__control:focus-within {
  box-shadow: 0 0 0 var(--focus-width) var(--status-delayed);
}

.lb-field--error .lb-field__hint {
  color: var(--status-delayed);
}

/* Native select in brand chrome. */
.lb-field--select .lb-field__control {
  position: relative;
  padding-inline-end: var(--space-2);
}

.lb-chrome .lb-field--select select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-inline-end: var(--space-6);
}

.lb-field__chevron {
  position: absolute;
  inset-inline-end: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}

/* An empty hint should not reserve a line — the calculator's origin notice only
   appears when a not-yet-live country snapped back to a live one. */
.lb-field__hint:empty {
  display: none;
}

/* `.is-invalid` is what a script sets; `--error` is what a template sets. They render
   identically on purpose — a field is wrong for the same reason either way, and the
   reader should not be able to tell which half of the stack noticed.
   The calculator uses this to say "fill these in" instead of quoting the 0.5 floor:
   a screenshot of a confident total over empty inputs is a promise. */
.lb-field.is-invalid .lb-field__control {
  border-color: var(--status-delayed);
}

.lb-field.is-invalid .lb-field__control:focus-within {
  border-color: var(--status-delayed);
  box-shadow: 0 0 0 var(--focus-width) var(--status-delayed);
}

/* -------------------------------------------------------------------------
 * Dimension trio — length x width x height
 *
 * A carton is three numbers read as one measurement, so they share a row and label
 * themselves underneath rather than carrying three labels above. Lives here rather
 * than with the calculator because both the console and the homepage's quick-quote
 * strip ask for the same carton, and two copies of this grid would drift.
 * ---------------------------------------------------------------------- */

.lb-dims {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
}

.lb-dims .lb-field {
  gap: var(--space-1);
}

.lb-dims .lb-field__hint {
  text-align: center;
  line-height: 16px;
}

/* -------------------------------------------------------------------------
 * Card — surfaces/Card.jsx
 *
 * Flat at rest. A shadow appears on hover only, and only when the card is a link.
 * ---------------------------------------------------------------------- */

.lb-card {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  padding: var(--space-6);
}

.lb-card--flush {
  padding: 0;
  overflow: hidden;
}

.lb-card--raised {
  background: var(--surface-raised);
}

.lb-card--quiet {
  background: var(--surface-quiet);
}

.lb-card--dark {
  background: var(--surface-dark);
  border-color: var(--surface-dark);
  color: var(--text-on-dark);
}

.lb-card--darker {
  background: var(--surface-darker);
  border-color: var(--surface-darker);
  color: var(--text-on-dark);
}

.lb-chrome a.lb-card,
.lb-chrome .lb-card--link {
  display: block;
  text-decoration: none;
  transition: box-shadow var(--dur-base) var(--ease-standard);
}

.lb-chrome a.lb-card:hover,
.lb-chrome .lb-card--link:hover {
  box-shadow: var(--shadow-hover);
  text-decoration: none;
}

/* Card header strip, as used on the address card and the quote slip. */
.lb-card__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  background: var(--surface-dark);
  color: var(--text-on-dark);
}

.lb-card__head--forest {
  background: var(--surface-darker);
}

.lb-card__body {
  padding: var(--space-5);
}

/* -------------------------------------------------------------------------
 * Status pill — status/StatusPill.jsx
 *
 * Never colour alone: every pill carries its text label.
 * ---------------------------------------------------------------------- */

.lb-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 5px 12px 5px 9px;
  border-radius: var(--radius-full);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  line-height: 1.7;
  white-space: nowrap;
}

.lb-pill--sm {
  gap: 5px;
  padding: 3px 9px 3px 7px;
  font-size: var(--text-caption);
}

.lb-pill--received {
  background: var(--status-received-bg);
  color: var(--status-received-ink);
}

.lb-pill--transit {
  background: var(--status-transit-bg);
  color: var(--status-transit-ink);
}

.lb-pill--customs {
  background: var(--status-customs-bg);
  color: var(--status-customs-ink);
}

/*
 * The Dhaka warehouse shares Harbour Blue with the China one. That is not borrowing a
 * status hue for variety — the rule this system has — it is the same meaning at a
 * different point on the route: goods at rest, in a warehouse, waiting to move. The two
 * are told apart by the label, which names the city, and inventing a sixth hue would
 * make "in a warehouse" mean two different colours.
 */
.lb-pill--at_dhaka {
  background: var(--status-received-bg);
  color: var(--status-received-ink);
}

.lb-pill--delivered {
  background: var(--status-delivered-bg);
  color: var(--status-delivered-ink);
}

.lb-pill--delayed {
  background: var(--status-delayed-bg);
  color: var(--status-delayed-ink);
}

/* Quiet outline pill — "আপনার কাজ" / "শীঘ্রই আসছে" tags. */
.lb-pill--quiet {
  background: transparent;
  border: var(--border-width) solid var(--border-default);
  color: var(--muted);
  font-weight: var(--weight-regular);
  font-size: var(--text-caption);
  padding: 3px 10px;
}

.lb-pill--brand {
  background: transparent;
  border: var(--border-width) solid var(--deep-green);
  color: var(--deep-green);
  font-size: var(--text-caption);
  padding: 3px 10px;
}

/* The amber badge that names which basis won the chargeable-weight comparison. */
.lb-pill--basis {
  background: var(--amber-tint-12);
  color: var(--amber-ink);
  font-size: var(--text-caption);
  font-weight: var(--weight-regular);
  padding: 2px 8px;
}

/* -------------------------------------------------------------------------
 * Route bar — how far along the route a shipment is
 *
 * Five steps: behind, here, ahead. (Not .lb-steps: that is the numbered list in a
 * blog post, and the two would have styled each other.) It began on the freight desk's rail and lives
 * here because the customer's screens draw the same bar; a stylesheet only the desk
 * loads could not give it to them. Markup comes from lb_route_bar().
 * ---------------------------------------------------------------------- */

/* Holds the bar and its spoken sentence; positioned so the sentence stays put. */
.lb-route {
  position: relative;
  display: block;
}

/* As many equal columns as there are steps — five today, and not the stylesheet's
   business to know that. */
.lb-routebar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-1);
  margin-block: var(--space-1);
}

.lb-routebar__seg {
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--border-default);
}

.lb-routebar__seg.is-done,
.lb-routebar__seg.is-current {
  background: var(--deep-green);
}

/* Where it is now is taller than where it has been, so the position reads without
   relying on the colour alone. */
.lb-routebar__seg.is-current {
  height: 10px;
  margin-block: -2px;
}

/* Delayed red, for the desk's stuck shipments — the only thing the bar's colour is
   allowed to say besides "this far". */
.lb-routebar--alert .lb-routebar__seg.is-done,
.lb-routebar--alert .lb-routebar__seg.is-current {
  background: var(--status-delayed);
}

/* -------------------------------------------------------------------------
 * Tracking timeline — status/TrackingTimeline.jsx
 * ---------------------------------------------------------------------- */

.lb-timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}

.lb-timeline__step {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: var(--space-3);
}

/* Flex column, not grid: the connector has to stretch to fill whatever height the
   step's text takes, otherwise it stops short of the next dot on any two-line step. */
.lb-timeline__marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

.lb-timeline__dot {
  width: 10px;
  height: 10px;
  margin-top: 6px;
  border-radius: var(--radius-full);
  background: var(--line);
}

.lb-timeline__line {
  width: 2px;
  flex: 1 1 auto;
  min-height: 34px;
  background: var(--line);
}

.lb-timeline__body {
  padding-bottom: var(--space-4);
}

.lb-timeline__step:last-child .lb-timeline__body {
  padding-bottom: 0;
}

.lb-timeline__title {
  display: block;
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  line-height: 1.7;
  color: var(--muted);
}

.lb-timeline__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  line-height: var(--lh-caption);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.lb-timeline__step--done .lb-timeline__dot,
.lb-timeline__step--done .lb-timeline__line {
  background: var(--deep-green);
}

.lb-timeline__step--done .lb-timeline__title {
  color: var(--ink);
}

.lb-timeline__step--current .lb-timeline__dot {
  width: 14px;
  height: 14px;
  background: var(--signal-amber);
  border: var(--border-width) solid var(--deep-green);
  animation: lb-pulse var(--pulse-dur) var(--ease-out) infinite;
}

.lb-timeline__step--current .lb-timeline__title {
  color: var(--ink);
}

/* -------------------------------------------------------------------------
 * Rate table — data/RateTable.jsx
 *
 * The source rounds the table itself; border-collapse defeats that in most
 * browsers, so the radius lives on a wrapper which doubles as the horizontal
 * scroll container the responsive rule requires.
 *
 * The block editor cannot put a class on a <table>, so post bodies match through
 * the figure's is-style-lb-table instead — one definition, two ways in.
 * ---------------------------------------------------------------------- */

.lb-table-wrap {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  overflow: hidden auto;
  overflow-x: auto;
  background: var(--surface-card);
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) {
  width: 100%;
  margin: 0;
  border: 0;
  border-collapse: collapse;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) th,
.lb-chrome :is( .lb-table, .is-style-lb-table > table ) td {
  padding: 12px var(--space-4);
  font-size: var(--text-small);
  line-height: var(--lh-small);
  text-align: left;
  border: 0;
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) thead tr {
  background: var(--deep-green);
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) th {
  color: var(--white);
  font-size: var(--text-overline);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) td {
  color: var(--ink);
  font-weight: var(--weight-regular);
}

.lb-chrome :is( .lb-table, .is-style-lb-table > table ) tbody tr {
  border-top: var(--border-width) solid var(--border-default);
}

/* Zebra rows at 3% Deep Green tint. */
.lb-chrome :is( .lb-table, .is-style-lb-table > table ) tbody tr:nth-child(even) {
  background: var(--green-tint-3);
}

/* Needs to out-specify the base cell rule above, or rate columns
   silently fall back to left-aligned and the tabular figures stop lining up. */
.lb-chrome :is( .lb-table, .is-style-lb-table > table ) th.is-numeric,
.lb-chrome :is( .lb-table, .is-style-lb-table > table ) td.is-numeric {
  text-align: right;
  font-weight: var(--weight-medium);
}

.lb-table__caption,
.lb-chrome :is( .lb-table, .is-style-lb-table > table ) caption {
  caption-side: bottom;
  text-align: left;
  padding-top: var(--space-3);
  font-family: var(--font-bangla), var(--font-body);
  font-size: var(--text-caption);
  line-height: var(--lh-caption);
  color: var(--muted);
}

/* -------------------------------------------------------------------------
 * Segmented control — air/sea, filter tabs, login tabs
 * ---------------------------------------------------------------------- */

.lb-segmented {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: var(--space-1);
  background: var(--green-tint-3);
  border: var(--border-width) solid var(--border-field);
  border-radius: var(--radius-md);
}

.lb-chrome .lb-segmented__option {
  min-height: var(--control-height);
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-bangla), var(--font-body);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  transition:
    background var(--dur-base) var(--ease-standard),
    color var(--dur-base) var(--ease-standard);
}

.lb-chrome .lb-segmented__option:hover {
  color: var(--deep-green);
}

.lb-chrome .lb-segmented__option[aria-selected="true"],
.lb-chrome .lb-segmented__option[aria-pressed="true"],
.lb-chrome .lb-segmented__option.is-active {
  background: var(--deep-green);
  color: var(--white);
}

/* Same control on a Paper band inverts its own ground. */
/*
 * Radio-driven segmented control: works with no script at all.
 *
 * Moved here from landing.css when the declaration form needed it. It was only ever in
 * the landing sheet because the calculator happened to be the first thing to use it —
 * and landing.css is not loaded in the portal, so the same markup rendered there came
 * out as two bare radio dots beside their labels.
 */
/* Radio-driven segmented control: works with no script at all. */
.lb-segmented--radio .lb-segmented__option {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.lb-segmented--radio input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.lb-segmented--radio .lb-segmented__option:has(input:checked) {
  background: var(--deep-green);
  color: var(--white);
}

.lb-segmented--radio .lb-segmented__option:has(input:focus-visible) {
  box-shadow: var(--ring-focus);
}

.lb-segmented--on-tint {
  background: var(--paper);
}

/* -------------------------------------------------------------------------
 * Tag pill — blog category filters
 * ---------------------------------------------------------------------- */

.lb-chrome .lb-tag {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-height-sm);
  padding: 0 var(--space-4);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-bangla), var(--font-body);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  text-decoration: none;
  transition:
    background var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard),
    color var(--dur-base) var(--ease-standard);
}

.lb-chrome .lb-tag:hover {
  border-color: var(--deep-green);
  color: var(--deep-green);
  text-decoration: none;
}

.lb-chrome .lb-tag.is-active,
.lb-chrome .lb-tag[aria-current="page"] {
  background: var(--deep-green);
  border-color: var(--deep-green);
  color: var(--white);
}

/* -------------------------------------------------------------------------
 * Stat card — dashboard figures and the landing trust strip
 * ---------------------------------------------------------------------- */

.lb-stat {
  display: grid;
  gap: var(--space-1);
  align-content: start;
}

.lb-stat--boxed {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: 18px;
}

.lb-stat__value {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 28px;
  line-height: 1.2;
  font-weight: var(--weight-bold);
  color: var(--deep-green);
}

.lb-stat__label {
  font-size: var(--text-small);
  color: var(--muted);
}

.lb-stat--alert .lb-stat__value {
  color: var(--status-delayed);
}

/* -------------------------------------------------------------------------
 * Quote slip — the worked chargeable-weight example
 *
 * Recurs across the landing calculator, the blog featured card and post bodies.
 * ---------------------------------------------------------------------- */

.lb-slip {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  overflow: hidden;
}

.lb-slip__head {
  padding: var(--space-3) 18px;
  background: var(--surface-darker);
  color: var(--text-on-dark);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
}

.lb-slip__body {
  display: grid;
  gap: 10px;
  padding: 18px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-body-sm);
}

.lb-slip__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  color: var(--ink);
}

.lb-slip__row > span:first-child {
  font-family: var(--font-bangla), var(--font-body);
}

.lb-slip__formula {
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--muted);
}

.lb-slip__value {
  font-weight: var(--weight-medium);
}

.lb-slip__row--total {
  border-top: var(--border-width) solid var(--border-default);
  padding-top: var(--space-3);
  color: var(--deep-green);
  font-weight: var(--weight-semibold);
}

.lb-slip__row--total .lb-slip__value {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--weight-semibold);
  color: var(--deep-green);
}

/* -------------------------------------------------------------------------
 * Notice — customs delay, inline hints, form-level messages
 * ---------------------------------------------------------------------- */

.lb-notice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) 18px;
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-quiet);
}

.lb-notice__text {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

/* Declared block because these are spans as often as paragraphs — the portal's
   notices nest them inside the icon+text row, where an inline title runs straight
   into its own explanation. */
.lb-notice__title,
.lb-notice__body {
  display: block;
}

.lb-notice__title {
  margin: 0;
  font-size: var(--text-body-sm);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.lb-notice__body {
  margin: 0;
  font-size: var(--text-small);
  color: var(--ink);
}

.lb-notice--alert {
  border-color: var(--status-delayed);
  background: var(--status-delayed-bg);
}

.lb-notice--alert .lb-icon {
  color: var(--status-delayed);
}

.lb-notice--quiet {
  border: 0;
  border-radius: var(--radius-md);
  background: var(--green-tint-6);
  padding: var(--space-3);
  font-size: var(--text-small);
  line-height: 20px;
  color: var(--ink);
  display: block;
}

/*
 * Amber-ruled callout used in post bodies.
 *
 * 1px, not 3px. The One Border Rule is absolute — "every border in the system is 1px",
 * and "strong emphasis is achieved by changing the border's colour, never its
 * thickness". A 3px bar down the side of a card is also the single most recognisable
 * tell of generated UI, which is the company this system least wants to keep.
 *
 * The emphasis does not come from the weight of the rule; it comes from the fact that
 * the rule is amber at all, on a page where amber appears roughly once. The tint wash
 * carries the rest, flat, the way every other emphasised surface here does.
 */
.lb-callout {
  margin: 0;
  border-left: var(--border-width) solid var(--signal-amber);
  background: var(--amber-tint-12);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-body-size);
  color: var(--ink);
}

/* -------------------------------------------------------------------------
 * Numbered steps — hero strip, post bodies, the login panel
 *
 * The numerals are structural: these lists are ordered processes where the order
 * carries meaning. Do not reuse the marker on an unordered list.
 * ---------------------------------------------------------------------- */

.lb-steps {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.lb-steps__item {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: var(--space-3);
  align-items: start;
}

.lb-steps__num {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-overline);
  color: var(--signal-amber);
  padding-top: 5px;
}

/* -------------------------------------------------------------------------
 * Accordion — FAQ and prohibited items
 * ---------------------------------------------------------------------- */

.lb-accordion {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}

.lb-accordion--card {
  border-radius: var(--radius-lg);
}

.lb-accordion > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 18px;
  cursor: pointer;
  list-style: none;
  font-size: var(--text-body-size);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

.lb-accordion > summary::-webkit-details-marker {
  display: none;
}

.lb-accordion > summary .lb-icon {
  color: var(--muted);
  transition: transform var(--dur-base) var(--ease-standard);
}

.lb-accordion[open] > summary .lb-icon {
  transform: rotate(180deg);
}

.lb-accordion__body {
  padding: 0 18px var(--space-4);
  font-size: var(--text-body-sm);
  color: var(--ink);
}

.lb-accordion__body > p {
  margin: 0;
}

/* -------------------------------------------------------------------------
 * Address card — patterns/AddressCard.jsx
 * ---------------------------------------------------------------------- */

.lb-address__lines {
  padding: var(--space-2) var(--space-5) var(--space-4);
  font-family: var(--font-body);
}

.lb-address__row {
  display: grid;
  /* 128px, not 108. Each row is its own grid, so this number is what keeps the labels
     in one column across rows — and it has to clear the longest field name in the set.
     SHIPPING MARK is that name, and at 108px it wrapped to two lines while its value
     stayed on one, which read as a broken row rather than a long label. */
  grid-template-columns: 128px minmax(0, 1fr);
  gap: var(--space-3);
  padding: 10px 0;
  border-top: var(--border-width) solid var(--border-default);
}

.lb-address__label {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
  font-weight: var(--weight-semibold);
  color: var(--muted);
}

.lb-address__value {
  font-size: var(--text-small);
  line-height: 22px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/*
 * Pre-signup teaser: the shape of the address is visible, the detail is not.
 *
 * No blur any more, and the reason is not cosmetic. The blur was hiding real text, so
 * it hid nothing from View Source, a crawler or a screen reader — the values are now
 * placeholders generated server-side (lb_address_lines_masked()) and there is nothing
 * left to obscure. A crisp run of dots also reads as *withheld* rather than as an
 * out-of-focus photograph, and it drops six composited layers off the first screen on
 * the low-end Android this page is built for.
 */
.lb-address__value--masked {
  color: var(--muted);
  letter-spacing: .06em;
  user-select: none;
}

.lb-address__id {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--signal-amber);
  color: var(--text-on-amber);
  border-radius: var(--radius-md);
  padding: 6px var(--space-3);
  font-family: var(--font-body);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

/* The pill names what the number is. "Shipping Mark" is the term the Chinese
   warehouse and the supplier's packing list use, so the field name is set in the
   same tracked Latin caps as the address labels above it and the number keeps the
   pill's own weight. */
.lb-address__id-label {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-overline);
  text-transform: uppercase;
}

/* -------------------------------------------------------------------------
 * Media frame — blog cards and post heroes
 * ---------------------------------------------------------------------- */

.lb-media {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--green-tint-3);
  overflow: hidden;
}

.lb-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lb-media--framed {
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg);
}

.lb-media--ruled {
  border-bottom: var(--border-width) solid var(--border-default);
}

/* Stand-in for a missing featured image: a quiet frame, not a broken one. */
.lb-media__placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--deep-green);
  opacity: .18;
}

/* -------------------------------------------------------------------------
 * Post card
 *
 * Lives here, not in blog.css, because three surfaces render it and only one of
 * them loads blog.css: the archive grid, the related-posts row under an article,
 * and the landing page's "সাম্প্রতিক লেখা" band. blog.css is enqueued on
 * is_home/is_archive/is_singular('post') only, so a copy of these rules kept there
 * left the homepage cards unpadded, untinted and with the placeholder icon adrift
 * in the frame's top-left corner. Card composition that more than one template
 * uses is components' job; blog.css keeps the archive-only chrome.
 * ---------------------------------------------------------------------- */

.lb-chrome a.lb-post-card {
  display: grid;
  align-content: start;
  background: var(--surface-card);
}

.lb-post-card__body {
  display: grid;
  align-content: start;
  gap: 10px;
  padding: var(--space-5) 22px 22px;
}

.lb-post-card__title {
  margin: 0;
  font-size: var(--text-h3);
  line-height: 1.4;
  font-weight: var(--weight-semibold);
  color: var(--deep-green);
  text-wrap: pretty;
}

.lb-post-card__excerpt {
  margin: 0;
  font-size: var(--text-small);
  color: var(--ink);
}

.lb-post-card__meta {
  font-size: var(--text-caption);
  color: var(--muted);
}
