Estamos mejorando nuestra Tienda, Portal de clientes y Aenormas para ofrecerte una mejor experiencia.
Si detectas cualquier incidencia o necesitas ayuda durante el proceso de compra, puedes contactarnos a través del chat o escribirnos a normas@aenor.com.
Nuestro equipo estará encantado de ayudarte.
Filtrar:
Se ha producido un error al procesar la plantilla.
The following has evaluated to null or missing:
==> getProduct(channelId, entry.getTitle()?trim) [in template "34352066712900#33336#153601689" at line 32, column 28]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #assign product = getProduct(channelI... [in template "34352066712900#33336#153601689" at line 32, column 9]
----
1<#setting url_escaping_charset="UTF-8">
2
3<#-- ===== Idiomas: helpers y datos al inicio ===== -->
4<#function getListTypeEntriesByERC erc>
5 <#attempt>
6 <#return restClient.get(
7 "/headless-admin-list-type/v1.0/list-type-definitions/by-external-reference-code/${erc}/list-type-entries?fields=key,name&sort"
8 ).items>
9 <#recover>
10 <#return []>
11 </#attempt>
12</#function>
13
14<#-- Siempre lista, nunca null -->
15<#assign LANG_ENTRIES = (getListTypeEntriesByERC("IDIOMAS_NORMAS_PICKLIST")?default([]))![]>
16
17<#function langLiteral key>
18 <#assign k = (key!"")?upper_case>
19 <#list LANG_ENTRIES as e>
20 <#if (e.key!"")?upper_case == k>
21 <#return e.name!"">
22 </#if>
23 </#list>
24 <#return key!"" >
25</#function>
26
27<section class="list-standards-section">
28 <div class="standards-container view-grid">
29 <#if entries?has_content>
30 <#assign channelId = getChannelId()>
31 <#list entries as entry>
32 <#assign product = getProduct(channelId, entry.getTitle()?trim)>
33 <#assign productId = product.productId />
34 <#assign cpDefinitionId = product.id />
35 <#assign productERC = product.externalReferenceCode />
36 <#assign categories = getProductCategories(channelId, product.productId)![]>
37 <#assign specs = getProductSpecifications(channelId, product.productId)![]>
38 <#assign status = getStatus(categories)!"" >
39 <#assign organism = getOrganism(categories)!"" >
40 <#assign currentStateDate = getCurrentStateDate(specs)!"" >
41 <#assign entryUrl = "">
42 <#attempt>
43 <#-- si el entry trae slug -->
44 <#assign entryUrl = "/p/${entry.getUrl()}">
45 <#recover>
46 <#-- si no, usa viewURL o el slug del product -->
47 <#assign entryUrl = (entry.getViewURL()!"")>
48 <#if !entryUrl?has_content && (product.slug?? && product.slug?has_content)>
49 <#assign entryUrl = "/p/${product.slug}">
50 </#if>
51 <#if !entryUrl?has_content>
52 <#assign entryUrl = "#">
53 </#if>
54 </#attempt>
55
56 <#-- Detalle de normas (idioma, formato, precio) -->
57 <#assign normasDetails = getNormasDetails(product.id)![]>
58
59 <#-- idiomas únicos -->
60 <#assign languages = []>
61 <#list normasDetails as n>
62 <#if n.language?? && n.language?has_content && !languages?seq_contains(n.language)>
63 <#assign languages = languages + [n.language]>
64 </#if>
65 </#list>
66
67 <#-- combinación por defecto -->
68 <#assign defaultLang = "">
69 <#assign defaultFmt = "">
70 <#assign defaultPrice = 0>
71 <#if normasDetails?has_content>
72 <#assign defaultLang = (normasDetails[0].language!"")>
73 <#assign defaultFmt = (normasDetails[0].format!"")>
74 <#assign defaultPrice = (normasDetails[0].price!'0')?number>
75 </#if>
76
77 <#-- formatos válidos para el idioma por defecto -->
78 <#assign formatsForDefault = []>
79 <#list normasDetails?filter(nd -> (nd.language!"") == defaultLang) as nd>
80 <#if nd.format?? && nd.format?has_content && !formatsForDefault?seq_contains(nd.format)>
81 <#assign formatsForDefault = formatsForDefault + [nd.format]>
82 </#if>
83 </#list>
84 <#if formatsForDefault?has_content && !formatsForDefault?seq_contains(defaultFmt)>
85 <#assign defaultFmt = formatsForDefault[0]>
86 </#if>
87
88 <#-- precio real para la combinación por defecto -->
89 <#list normasDetails as nd>
90 <#if (nd.language!"") == defaultLang && (nd.format!"") == defaultFmt>
91 <#assign defaultPrice = (nd.price!'0')?number>
92 </#if>
93 </#list>
94
95 <#assign hasOptions = (languages?has_content && formatsForDefault?has_content && (defaultLang?has_content) && (defaultFmt?has_content))>
96
97 <div class="item-result-buscador item-standard"
98 data-entrytype="Norma"
99 data-code="${(product.externalReferenceCode!entry.getTitle())?html}"
100 data-title="${product.name?html}">
101 <#if organism?has_content>
102 <div class="tag-standard">${organism}</div>
103 <#else>
104 <div class="tag-standard">TAG</div>
105 </#if>
106
107 <div class="info-standard">
108 <a href=${entryUrl} data-senna-off="true"><h3 class="title-standard">${product.name}</h3></a>
109
110 <div class="status-box">
111
112 <#if status?? && status?has_content>
113 <#assign statusTagClass = ''>
114
115 <#if status?trim?upper_case == 'EN VIGOR'>
116 <#assign statusTagClass = 'tag-success'>
117 <#elseif status?trim?upper_case == 'ANULADA'>
118 <#assign statusTagClass = 'tag-danger'>
119 <#elseif status?trim?upper_case == 'PROYECTO'>
120 <#assign statusTagClass = 'tag-blue'>
121 </#if>
122
123 <#if statusTagClass?? && statusTagClass?has_content>
124 <#assign statusTagClass = "status-standard " + statusTagClass>
125 </#if>
126
127 <div class="badge ${statusTagClass}">${status}</div>
128 </#if>
129
130 <span class="date-standard">
131 <#if currentStateDate?has_content>
132 ${currentStateDate?date.iso?string('yyyy-MM-dd')}
133 <#else>
134 -
135 </#if>
136 </span>
137 </div>
138
139 <div class="description-text">
140 ${product.description}
141 </div>
142
143 <div class="price-container">
144 <span class="price price-ae"></span>
145 </div>
146
147 <#if hasOptions>
148 <div data-productid="${productId}" data-erc="${productERC}" class="options-standard selector-language_format">
149 <select class="form-control select-language">
150 <#list languages as l>
151 <option value="${l?html}" <#if l == defaultLang>selected</#if>>
152 ${langLiteral(l)?html}
153 </option>
154 </#list>
155 </select>
156 <select class="form-control select-format">
157 <#list formatsForDefault as f>
158 <option value="${f?html}" <#if f == defaultFmt>selected</#if>>
159 ${f?html}
160 </option>
161 </#list>
162 </select>
163 </div>
164 <#else>
165 <div class="standard-not-available">
166 ${languageUtil.get(locale, "ecom-get_norma_mail")}
167 </div>
168 </#if>
169
170 <#if hasOptions>
171 <button
172 class="standard-button"
173 aria-disabled="false"
174 disabled>
175 ${languageUtil.get(locale, "ecom-add_cart")}
176 </button>
177 </#if>
178 </div>
179
180 <#-- Datos para JS -->
181 <#if hasOptions>
182 <script type="application/json" class="normas-data">[
183 <#list normasDetails as n>
184 <#-- solo pares válidos -->
185 <#if (n.language?? && n.language?has_content) && (n.format?? && n.format?has_content)>
186 {
187 "format": "${(n.format!"")?js_string}",
188 "language": "${(n.language!"")?js_string}",
189 "price": ${(n.price!'0')?c}
190 }<#if n_has_next>,</#if>
191 </#if>
192 </#list>
193 ]</script>
194 <script type="application/json" class="lang-map">{
195 <#list languages as l>
196 "${(l!"")?upper_case?js_string}": "${langLiteral(l)?js_string}"<#if l_has_next>,</#if>
197 </#list>
198 }</script>
199 </#if>
200 </div>
201 </#list>
202 <#else>
203 <div class="search-results-add-custom-empty-message"></div>
204 </#if>
205 </div>
206</section>
207
208<#-- ===== Helpers REST ===== -->
209<#function getChannelId>
210 <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels?filter=name eq 'Aenor España'&sort").items[0].id>
211</#function>
212
213<#function getProduct channelId name>
214 <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products?filter=name eq '${name?url}'&sort").items[0]>
215</#function>
216
217<#function getProductCategories channelId productId>
218 <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/categories?sort").items>
219</#function>
220
221<#function getProductSpecifications channelId productId>
222 <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/product-specifications?sort").items>
223</#function>
224
225<#function getCurrentStateDate specifications>
226 <#list specifications as specification>
227 <#if specification.specificationKey == 'current-state-date'>
228 <#return specification.value>
229 </#if>
230 </#list>
231</#function>
232
233<#function getStatus categories>
234 <#list categories as category>
235 <#if category.vocabulary == 'status'>
236 <#return category.title>
237 </#if>
238 </#list>
239</#function>
240
241<#function getOrganism categories>
242 <#list categories as category>
243 <#if category.vocabulary == 'organismos'>
244 <#return category.name>
245 </#if>
246 </#list>
247</#function>
248
249<#function getNormasDetails productId>
250 <#return restClient.get("/c/standards/?filter=r_standards_CPDefinitionId eq '${productId}'").items>
251</#function>
252
253<script>
254jQuery(async function($){
255 let API_HOST = null;
256 function euros(v){
257 var n = Number(v) || 0;
258 return n.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €';
259 }
260 function uniq(a){ return Array.from(new Set(a)); }
261
262 async function waitForEcomGlobalScripts(timeoutMs){
263 const start = Date.now();
264 return new Promise((resolve, reject) => {
265 (function check(){
266 if (window.ecomGlobalScripts?.functions?.getFieldCXCustomConfig && window.ecomGlobalScripts?.properties?.cxCustomConfigsNames) {
267 return resolve();
268 }
269 if (Date.now() - start > timeoutMs) return reject(new Error('ecomGlobalScripts no disponible a tiempo'));
270 requestAnimationFrame(check);
271 })();
272 });
273 }
274
275 const getApiHost = async () => {
276 if (API_HOST) return API_HOST;
277 try {
278 await waitForEcomGlobalScripts(5000);
279 API_HOST = await window.ecomGlobalScripts.functions.getFieldCXCustomConfig(
280 window.ecomGlobalScripts.properties.cxCustomConfigsNames.defaultName, "webApiUrl"
281 );
282 } catch (err) {
283 console.error('No se pudo resolver API_HOST', err);
284 }
285 return API_HOST;
286 };
287
288 function fill($sel, values, textFn){
289 var keep = $sel.val();
290 $sel.empty();
291 values.forEach(function(v){
292 $sel.append($('<option>', { value: v, text: textFn ? textFn(v) : v }));
293 });
294 if(keep && values.indexOf(keep) !== -1){ $sel.val(keep); }
295 else if(values.length){ $sel.val(values[0]); }
296 }
297
298 function relabel($sel, textFn){
299 $sel.find('option').each(function(){
300 var v = $(this).attr('value');
301 $(this).text(textFn ? textFn(v) : v);
302 });
303 }
304
305 function toUC(s){ return (s||'').toString().toUpperCase(); }
306 function emitCartError(msg){
307 try {
308 window.dispatchEvent(new CustomEvent('cart:error', { detail: { message: msg || 'Error al añadir el producto a la cesta' } }));
309 } catch (e) {}
310 }
311 async function resolveProductId(entryType, code, codIdioma, codFormato){
312 const host = await getApiHost();
313 if (!host) return '';
314 try{
315 var res = await fetch(host + '/product/getProductId', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ entryType: entryType, code: code, codIdioma: codIdioma, codFormato: codFormato }), credentials:'omit' });
316 if(!res.ok) throw new Error('HTTP '+res.status);
317 var data = await res.json();
318 return (data && (data.id)) || '';
319 } catch(e){ return ''; }
320 }
321 function getQueue(){ try { return JSON.parse(localStorage.getItem('cartQueued') || '[]'); } catch(e){ return []; } }
322 function setQueue(q){ localStorage.setItem('cartQueued', JSON.stringify(q)); }
323 function queueItem(item){
324 var q=getQueue();
325 var pid=(item&&item.productid)?String(item.productid):'';
326 var amt=Number(item&&item.amount)||1;
327 var prc=(item&&typeof item.price!=='undefined')?Number(item.price):undefined;
328 var nm =(item&&typeof item.name!=='undefined')?String(item.name):undefined;
329 var ci =(item&&typeof item.idioma!=='undefined')?String(item.idioma):undefined;
330 var cf =(item&&typeof item.formato!=='undefined')?String(item.formato):undefined;
331 if(!pid) return;
332 var idx=-1; for(var i=0;i<q.length;i++){ var qp=q[i]&&q[i].productid?String(q[i].productid):''; if(qp===pid){ idx=i; break; } }
333 if(idx>=0){ var cur=Number(q[idx].amount)||0; q[idx].amount=Math.max(1, cur+amt); if(typeof prc!=='undefined'){ q[idx].price=prc; } if(typeof nm!=='undefined'){ q[idx].name=nm;} if(typeof ci!=='undefined'){ q[idx].idioma=ci;} if(typeof cf!=='undefined'){ q[idx].formato=cf;} }
334 else { var obj={ amount: Math.max(1,amt), productid: pid }; if(typeof prc!=='undefined') obj.price=prc; if(typeof nm!=='undefined') obj.name=nm; if(typeof ci!=='undefined') obj.idioma=ci; if(typeof cf!=='undefined') obj.formato=cf; q.push(obj); }
335 setQueue(q);
336 }
337 function bumpBadge(amt){ var cur=parseInt(localStorage.getItem('cartCount')||'0',10)||0; var next=Math.max(0, cur+(amt|0)); localStorage.setItem('cartCount', String(next)); window.dispatchEvent(new CustomEvent('cart:updated', { detail:{ count: next }})); }
338
339 function initStandardCard($card){
340 var dataNode = $card.find('script.normas-data')[0];
341 if(!dataNode) return; // sin datos -> nada que sincronizar
342
343 var data = [];
344 try { data = JSON.parse(dataNode.textContent); } catch(e) { data = []; }
345 if(!data.length) return;
346
347 var mapNode = $card.find('script.lang-map')[0];
348 var langMap = {};
349 try { if(mapNode) langMap = JSON.parse(mapNode.textContent); } catch(e) { langMap = {}; }
350
351 var $lang = $card.find('.select-language');
352 var $fmt = $card.find('.select-format');
353 var $price = $card.find('.price-ae');
354
355 function labelOf(lang){ return langMap[toUC(lang)] || lang; }
356 function formatsFor(lang){
357 return uniq(data.filter(function(d){ return d.language === lang; }).map(function(d){ return d.format; }));
358 }
359 function languagesFor(fmt){
360 return uniq(data.filter(function(d){ return d.format === fmt; }).map(function(d){ return d.language; }));
361 }
362 function priceOf(lang, fmt){
363 var m = data.find(function(d){ return d.language === lang && d.format === fmt; });
364 return m ? Number(m.price) || 0 : 0;
365 }
366
367 function onLanguageChange(){
368 var lang = $lang.val();
369 var fmts = formatsFor(lang);
370 fill($fmt, fmts, null);
371 $price.text(euros(priceOf(lang, $fmt.val())));
372 }
373 function onFormatChange(){
374 var fmt = $fmt.val();
375 var langs = languagesFor(fmt);
376 fill($lang, langs, labelOf);
377 $price.text(euros(priceOf($lang.val(), fmt)));
378 }
379
380 var l0 = $lang.val();
381 var f0 = $fmt.val();
382 if(!data.find(function(d){ return d.language === l0 && d.format === f0; })){
383 onLanguageChange();
384 } else {
385 $price.text(euros(priceOf(l0, f0)));
386 }
387
388 relabel($lang, labelOf); // literal de idioma
389
390 $lang.off('change.std').on('change.std', onLanguageChange);
391 $fmt.off('change.std').on('change.std', onFormatChange);
392
393 // Añadir a la cesta
394 $card.find('.standard-button').off('click.add').on('click.add', function(e){
395 var btn = this;
396 if ($(btn).hasClass('disabled')) { e.preventDefault(); return; }
397 var run = async function(){
398 e.preventDefault();
399 var orderId = localStorage.getItem('salesOrderId');
400 var entryType = ($card.data('entrytype') || 'Norma');
401 var code = ($card.data('code') || '').toString();
402 var $langSel = $card.find('.select-language');
403 var $fmtSel = $card.find('.select-format');
404 var codIdioma = ($langSel.filter(function(){ return this.value; }).first().val() || $langSel.val() || '').toString();
405 var codFormato = ($fmtSel.filter(function(){ return this.value; }).first().val() || $fmtSel.val() || '').toString();
406 if ((!codIdioma || !codFormato) && data && data.length){
407 codIdioma = codIdioma || (data[0].language || data[0].codLanguage || '');
408 codFormato = codFormato || (data[0].format || data[0].codFormat || '');
409 }
410 if (!code) { code = ($card.find('.title-standard').text() || '').trim(); }
411 var priceToSend = Number(priceOf(codIdioma, codFormato)) || 0;
412 var resolvedId = await resolveProductId(entryType, code, codIdioma, codFormato);
413 if (!resolvedId) {
414 emitCartError('Error al añadir el producto a la cesta');
415 return;
416 }
417 var productIdForCart = resolvedId;
418 if (orderId) {
419 var host = await getApiHost();
420 if (!host) {
421 emitCartError('Error al añadir el producto a la cesta');
422 return;
423 }
424 var payload = {
425 salesorderid: orderId || '',
426 amount: 1,
427 productid: productIdForCart,
428 price: priceToSend,
429 name: ($card.data('title') || '').toString(),
430 idioma: codIdioma,
431 formato: codFormato
432 };
433 bumpBadge(1);
434 fetch(host + '/shoppingProcess/newSalesOrderProduct', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload), credentials:'omit' })
435 .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); setTimeout(function(){ window.dispatchEvent(new CustomEvent('cart:updated')); }, 300); })
436 .catch(function(){ bumpBadge(-1); emitCartError('Error al añadir el producto a la cesta'); });
437 } else {
438 queueItem({ amount: 1, productid: productIdForCart, price: priceToSend, name: ($card.data('title')||'').toString(), idioma: codIdioma, formato: codFormato });
439 bumpBadge(1);
440 }
441 };
442 var helper = window.ecomGlobalScripts?.functions?.withButtonSpinner;
443 if (typeof helper === 'function') {
444 return helper(btn, run, { spinnerClass: 'spinner-border spinner-border-sm text-light', mode: 'replace' });
445 }
446 return run();
447 });
448 }
449
450 // Alturas por fila
451 function adjustHeightsByRow(){
452 var $cards = $('.list-standards-section .item-standard');
453 var $titles = $cards.find('.title-standard');
454 var $descs = $cards.find('.description-text');
455 var $infos = $cards.find('.info-standard');
456
457 $cards.css('height','auto');
458 $titles.css('height','auto');
459 $descs.css('height','auto');
460 $infos.css('height','auto');
461
462 if($(window).width() <= 767.98) return;
463
464 var rows = [];
465 var tol = 4; // tolerancia de alineación
466 $cards.each(function(){
467 var $c = $(this);
468 var top = Math.round($c.position().top);
469 var row = rows.find(function(r){ return Math.abs(r.top - top) <= tol; });
470 if(!row){ row = { top: top, cards: [] }; rows.push(row); }
471 row.cards.push($c);
472 });
473
474 rows.forEach(function(r){
475 var hCard = 0, hTitle = 0, hDesc = 0, hInfo = 0;
476 r.cards.forEach(function($c){
477 hCard = Math.max(hCard, $c.outerHeight());
478 hTitle = Math.max(hTitle, $c.find('.title-standard').outerHeight());
479 hDesc = Math.max(hDesc, $c.find('.description-text').outerHeight());
480 hInfo = Math.max(hInfo, $c.find('.info-standard').outerHeight());
481 });
482 r.cards.forEach(function($c){
483 $c.height(hCard);
484 $c.find('.title-standard').height(hTitle);
485 $c.find('.description-text').height(hDesc);
486 $c.find('.info-standard').height(hInfo);
487 });
488 });
489 }
490
491 async function init(){
492 $('.list-standards-section .item-standard').each(function(){ initStandardCard($(this)); });
493 adjustHeightsByRow();
494 setTimeout(adjustHeightsByRow, 50);
495 }
496
497 var so = localStorage.getItem('salesOrderId'); // flushQueue gestionado por header
498 await init();
499 $(window).on('resize', init);
500});
501</script>
502
503<style>
504.list-standards-section { margin: 40px auto 35px; }
505.list-standards-section .header-section { border-bottom: 1px solid #dbdbdb; margin-bottom: 32px; display: flex; justify-content: space-between; margin-left: 2px; margin-right: 2px; align-items: center; }
506.list-standards-section .header-section .order-elements { font-family: Segoe-UI-This; font-size: 16px; font-weight: 400; line-height: 23px; text-align: left; color: #2d2d2b; }
507.list-standards-section .title-section { font-family: SohoStd-Medium; font-size: 24px; font-weight: 500; line-height: 28.8px; text-align: left; color: var(--brand-color-3, #29337f); }
508.list-standards-section .standards-container { display: flex; flex-wrap: wrap; gap: 20px 0; padding-right: 0; padding-left: 0; }
509.list-standards-section .item-standard { position: relative; border: 1px solid #e0e0e0; padding: 16px 14px; border-radius: 4px; display: flex; flex-direction: column; }
510.list-standards-section .tag-standard { position: absolute; top: -10px; left: 16px; padding: 4px 10px; border-radius: 4px; background-color: #6a9bd3; color: #fff; font-weight: bold; font-size: 12px; z-index: 5; }
511.list-standards-section .date-ISO { font-family: Segoe-UI-This; font-size: 14px; font-weight: 400; line-height: 18.62px; text-align: left; color: #444; }
512.list-standards-section .title-standard { font-family: SohoGothicPro-Regular; font-size: 16px; font-weight: bold; color: #1a4b94; line-height: 24px; text-align: left; padding-top: 10px;}
513.list-standards-section .description-text { margin-top: 10px; margin-bottom: 12px; font-family: SohoGothicPro-Regular; font-weight: 400; line-height: 24px; font-size: 13px; text-align: left; color: #333; }
514.list-standards-section .info-standard { display: flex; flex-direction: column; flex: 1; }
515.list-standards-section .info-standard .status-box .tag-success {background: #2a7a36; color: #fff;}
516.list-standards-section .info-standard .status-box .tag-danger {background: #c00000; color: #fff;}
517.list-standards-section .info-standard .status-box .tag-blue {background: #0078c0; color: #fff;}
518.list-standards-section .price-container { display: flex; flex-direction: column; text-align: left; letter-spacing: -0.02em; margin-top: auto; margin-bottom: 16px; }
519.list-standards-section .price-container .price-ae { font-size: 23px; font-weight: bold; line-height: 22px; margin-bottom: 10px; color: var(--brand-color-1, #1f57a3); }
520.list-standards-section .standard-not-available {
521 border-style: solid;
522 border-width: 2px;
523 background-color: #f2dede;
524 border-color: #ebcccc;
525 color: #a94442;
526 margin-left: -2px !important;
527 padding-left: 4px !important;
528 margin-top: 25px;
529}
530.list-standards-section .standard-button { border: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; -moz-appearance: none; padding: 17px; width: 100%; text-align: center; display: block; background-color: var(--brand-color-1, #1f57a3); color: #fff; text-transform: uppercase; font-family: SohoStd-Medium; font-size: 14px; font-weight: 500; line-height: 14px; cursor: pointer; text-decoration: none; }
531.list-standards-section .standard-button:disabled,
532.list-standards-section .standard-button[disabled],
533.list-standards-section .standard-button.disabled,
534.list-standards-section .standard-button.ecom-btn-loading {
535 opacity: .6;
536 pointer-events: none;
537 filter: brightness(0.85);
538}
539.list-standards-section .standard-button:hover,
540.list-standards-section .standard-button:focus,
541.list-standards-section .standard-button:focus-visible,
542.list-standards-section .standard-button:active {
543 background-color: var(--brand-color-1, #1f57a3);
544 color: #fff;
545 text-decoration: none;
546 outline: 2px solid var(--brand-color-2, #6a9bd3);
547 outline-offset: 2px;
548 box-shadow: 0 0 0 3px rgba(106, 155, 211, 0.35);
549}
550.list-standards-section .standard-button:active {
551 filter: brightness(0.85);
552}
553.list-standards-section .view-grid{ gap: 20px 3.5%; }
554.list-standards-section .view-grid .item-standard { width: 31%; }
555@media (max-width:1200px){ .list-standards-section .view-grid .item-standard { width: 48%; } }
556@media (max-width: 576px) { .list-standards-section .view-grid .item-standard { width: 100%; } }
557.options-standard { display: flex; gap: 10px; margin-bottom: 16px; border: none; }
558.options-standard .select-language,
559.options-standard .select-format {
560 background-color: #f5f5f5;
561 border: 1px solid #d0d0d0;
562 color: #2d2d2b;
563 font-size: 13px;
564 height: 38px;
565}
566.options-standard .select-language:disabled,
567.options-standard .select-format:disabled {
568 background-color: #f5f5f5;
569 color: #2d2d2b;
570 opacity: 1;
571}
572.options-standard .select-language { flex: 2; }
573.options-standard .select-format { flex: 1; }
574select.form-control,
575select.form-control:focus,
576select.form-control:focus-visible {
577 background-image: url(/documents/d/global/ico-chevron-down);
578 background-size: 18px 10px;
579 background-position-x: 95%;
580 background-repeat: no-repeat;
581 position: relative;
582}
583.status-standard { margin-right: 10px; background-color: #107510; color: white; font-size: 12px; padding: 2px 6px; border-radius: 3px; font-weight: bold; }
584.date-standard { font-size: 12px; color: #666; }
585.js-checks-container { display: none; }
586</style>










