AENOR Logo

Normas DIN

144175 Resultados disponibles

Filtrar:

(109283)
(34892)
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>